You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
daemon start reports an invalid config.json as INTERNAL (exit 1), not a request error (exit 2) #1084
simlock daemon start refuses a config.json that fails validation with code INTERNAL and exit 1:
--gateway daemon start with http.enabled: false in the gateway's config.json: {"error":{"code":"INTERNAL","message":"Invalid config value for \"http.enabled\": expected true in gateway mode (a gateway is reached over HTTP)"}}
--local daemon start on a joined worker (gateway.url set) with http.enabled: true: {"error":{"code":"INTERNAL","message":"Invalid config value for \"http.enabled\": expected false when gateway.url is set (joined workers are reached through the gateway)"}}
What you expected
A wrong config value is a wrong request, not an internal failure: exit 2 with a request-error code, as simlock config set already does for the same values (website docs, worker/configuration: "refused with exit code 2"). Rerunning unchanged fails again, which is what exit 2 means in the errors reference.
How to reproduce
The two unit tests in src/cli/index.test.ts ("starting a gateway refuses to launch when its config.json fails gateway validation" and "--local daemon start with no daemon listening refuses a joined worker's HTTP conflict before any launch") assert only not.toBe(0); changing them to toBe(2) fails on main.
Environment
main at 1eff6b8, found by the test audit in #1039.
Confirmed on main at ce8fea8. The two tests the issue names now assert exit 2 and { code: "USAGE", message } with the message unchanged. Both fail with exit 1. Branch bug/1084-repro, src/cli/index.test.ts:
"--gateway daemon start refuses a config.json that fails gateway validation with exit 2 and USAGE, before any launch"
"--local daemon start with no daemon listening refuses a joined worker's HTTP conflict with exit 2 and USAGE, before any launch"
pnpm exec vitest run --project unit src/cli/index.test.ts -t "exit 2 and USAGE, before any launch"
AssertionError: expected 1 to be 2 (index.test.ts:3384, :3472)
Tests 2 failed
Root cause
Defect. AutoLaunchAdminConnector.connect calls checkConfig() at src/cli/environment.ts:54 (defined at :294). That call runs loadConfig, and the ConfigError it throws reaches runCli's error boundary unwrapped. ConfigError is neither a UsageError nor a SimlockError, so cliErrorCode returns INTERNAL (src/cli/errors.ts:53) and errorExitCode returns 1 (:62). config set wraps the same error in UsageError (src/cli/commands/config.ts:52). The symptom shows up in daemon start, but the cause is in the shared auto-launch path: every auto-launching command (status, lease, ...) is affected.
Simplest fix
In checkConfig (environment.ts:294), catch ConfigError and rethrow it as new UsageError(error.message). Export ConfigError from src/core/index.ts, where it is not exported today. USAGE follows the config set precedent. It is the code the test pins.
Alternatives rejected
Map every checkConfig error to USAGE: a read failure such as EACCES is not a wrong request.
Map ConfigError by name in errors.ts: the error stays a core class that the CLI only recognises by name, and the boundary gets one more lazy check.
Use BAD_REQUEST: that code means a daemon refused a request. Here no daemon was reached.
Risk
Invalid JSON in config file is also a ConfigError, so it becomes exit 2 as well. Intended.
The DAEMON_STARTUP_FAILED row in website/.../using-devices/errors.mdx:75 says a bad config file is a common cause. After this fix, the CLI precheck reports a bad config as USAGE, so that row needs updating.
lazy-loading.test.ts: importing ConfigError must not load core on the router path.
Activity
test(audit): 13 fewer tests in cli, daemon, edge and five more files,…
V3RON commentedon Oct 31, 2026
Reproduction
Confirmed on main at ce8fea8. The two tests the issue names now assert exit 2 and
{ code: "USAGE", message }with the message unchanged. Both fail with exit 1. Branchbug/1084-repro,src/cli/index.test.ts:Root cause
Defect.
AutoLaunchAdminConnector.connectcallscheckConfig()atsrc/cli/environment.ts:54(defined at :294). That call runsloadConfig, and theConfigErrorit throws reachesrunCli's error boundary unwrapped.ConfigErroris neither aUsageErrornor aSimlockError, socliErrorCodereturnsINTERNAL(src/cli/errors.ts:53) anderrorExitCodereturns 1 (:62).config setwraps the same error inUsageError(src/cli/commands/config.ts:52). The symptom shows up indaemon start, but the cause is in the shared auto-launch path: every auto-launching command (status,lease, ...) is affected.Simplest fix
In
checkConfig(environment.ts:294), catchConfigErrorand rethrow it asnew UsageError(error.message). ExportConfigErrorfromsrc/core/index.ts, where it is not exported today.USAGEfollows theconfig setprecedent. It is the code the test pins.Alternatives rejected
checkConfigerror toUSAGE: a read failure such as EACCES is not a wrong request.ConfigErrorby name inerrors.ts: the error stays a core class that the CLI only recognises by name, and the boundary gets one more lazy check.BAD_REQUEST: that code means a daemon refused a request. Here no daemon was reached.Risk
Invalid JSON in config fileis also aConfigError, so it becomes exit 2 as well. Intended.DAEMON_STARTUP_FAILEDrow inwebsite/.../using-devices/errors.mdx:75says a bad config file is a common cause. After this fix, the CLI precheck reports a bad config asUSAGE, so that row needs updating.lazy-loading.test.ts: importingConfigErrormust not loadcoreon the router path.Written by an agent.
test(e2e): daemon start with a stale mode key exits 2 USAGE; docs: co…
test(e2e): a lease TTL config the CLI rejects exits 2 USAGE (#1084)
fix(cli): report an invalid config.json as USAGE, exit 2 (callstackin…