Skip to content

Commit 10c5e2a

Browse files
committed
fix(bootstrap): eliminate spurious error message on successful CLI execution
Resolves issue where "Bootstrap error: command failed" was printed after every command execution, even when commands succeeded. Root cause: Calling process.exit() inside async functions can trigger promise rejections during Node.js shutdown, causing the catch block to fire spuriously. Solution: Return exit codes from async functions and call process.exit() at the top level after all async operations complete cleanly. Changes: - executeCli(): Return exit code instead of calling process.exit() - findAndExecuteCli(): Propagate exit code from executeCli() - bootstrap-smol.mts: Call process.exit() in .then() handler - bootstrap-npm.mts: Same fix for npm wrapper - bootstrap-sea.mts: Same fix for SEA binary Fixes affect all three bootstrap variants to ensure consistency.
1 parent 895c0a6 commit 10c5e2a

File tree

6 files changed

+39
-27
lines changed

6 files changed

+39
-27
lines changed

packages/bootstrap/dist/bootstrap-npm.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/bootstrap/dist/bootstrap-smol.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/bootstrap/src/bootstrap-npm.mts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,16 @@ import { findAndExecuteCli, getArgs } from './shared/bootstrap-shared.mjs'
1414

1515
async function main() {
1616
const args = getArgs()
17-
await findAndExecuteCli(args)
17+
return await findAndExecuteCli(args)
1818
}
1919

2020
// Run the bootstrap.
21-
main().catch((e) => {
22-
logger.error(`Bootstrap error: ${e instanceof Error ? e.message : String(e)}`)
23-
process.exit(1)
24-
})
21+
main()
22+
.then((exitCode) => {
23+
// Exit with the code returned by the CLI.
24+
process.exit(exitCode)
25+
})
26+
.catch((e) => {
27+
logger.error(`Bootstrap error: ${e instanceof Error ? e.message : String(e)}`)
28+
process.exit(1)
29+
})

packages/bootstrap/src/bootstrap-sea.mts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@ import { findAndExecuteCli, getArgs } from './shared/bootstrap-shared.mjs'
1515

1616
async function main() {
1717
const args = getArgs()
18-
await findAndExecuteCli(args)
18+
return await findAndExecuteCli(args)
1919
}
2020

2121
// Run the bootstrap.
22-
main().catch((e) => {
23-
// Use process.stderr.write() directly to avoid console access during early bootstrap.
24-
process.stderr.write(`Bootstrap error: ${e instanceof Error ? e.message : String(e)}\n`)
25-
process.exit(1)
26-
})
22+
main()
23+
.then((exitCode) => {
24+
// Exit with the code returned by the CLI.
25+
process.exit(exitCode)
26+
})
27+
.catch((e) => {
28+
// Use process.stderr.write() directly to avoid console access during early bootstrap.
29+
process.stderr.write(`Bootstrap error: ${e instanceof Error ? e.message : String(e)}\n`)
30+
process.exit(1)
31+
})

packages/bootstrap/src/bootstrap-smol.mts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,18 @@ import { findAndExecuteCli, getArgs } from './shared/bootstrap-shared.mjs'
1414

1515
async function main() {
1616
const args = getArgs()
17-
await findAndExecuteCli(args)
17+
return await findAndExecuteCli(args)
1818
}
1919

2020
// Run the bootstrap.
21-
main().catch((e) => {
22-
// Suppress spurious "command failed" error from process.exit() during CLI execution.
23-
const errorMsg = e instanceof Error ? e.message : String(e)
24-
if (errorMsg.includes('command failed')) {
25-
return
26-
}
27-
// Use process.stderr.write() directly to avoid console access during early bootstrap.
28-
process.stderr.write(`Bootstrap error: ${errorMsg}\n`)
29-
process.exit(1)
30-
})
21+
main()
22+
.then((exitCode) => {
23+
// Exit with the code returned by the CLI.
24+
process.exit(exitCode)
25+
})
26+
.catch((e) => {
27+
// Use process.stderr.write() directly to avoid console access during early bootstrap.
28+
const errorMsg = e instanceof Error ? e.message : String(e)
29+
process.stderr.write(`Bootstrap error: ${errorMsg}\n`)
30+
process.exit(1)
31+
})

packages/bootstrap/src/shared/bootstrap-shared.mjs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ export async function executeCli(cliPath, args) {
150150
})
151151
}
152152

153-
process.exit(result.code ?? 0)
153+
return result.code ?? 0
154154
}
155155

156156
/**
@@ -199,6 +199,7 @@ export async function downloadCli() {
199199

200200
/**
201201
* Find and execute the CLI from the downloaded package.
202+
* Returns exit code from CLI execution.
202203
*/
203204
export async function findAndExecuteCli(args) {
204205
// Download CLI if needed.
@@ -210,12 +211,12 @@ export async function findAndExecuteCli(args) {
210211

211212
// Execute the CLI loader.
212213
if (existsSync(cliEntry)) {
213-
await executeCli(cliEntry, args)
214+
return await executeCli(cliEntry, args)
214215
}
215216

216217
// If we can't find the CLI, exit with error.
217218
logger.error('Socket CLI installation failed')
218219
logger.error(' CLI entry point not found after installation')
219220
logger.error(` Looked in: ${cliEntry}`)
220-
process.exit(1)
221+
return 1
221222
}

0 commit comments

Comments
 (0)