{"record":{"id":"e5d419c43d1848c6","repo":"can1357/oh-my-pi","slug":"ssh-exited-with-code-exitcode","errorCode":null,"errorMessage":"ssh exited with code ${exitCode}","messagePattern":"ssh exited with code (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/cli/auth-broker-cli.ts","lineNumber":404,"sourceCode":"\t\t`${APP_NAME} auth-broker login ${provider}`,\n\t];\n\tif (dryRun) {\n\t\tprocess.stdout.write(`ssh ${sshArgs.map(a => (a.includes(\" \") ? `'${a}'` : a)).join(\" \")}\\n`);\n\t\treturn;\n\t}\n\tconst sshBin = $which(\"ssh\");\n\tif (!sshBin) {\n\t\tthrow new Error(\"ssh binary not found in PATH\");\n\t}\n\tconst proc = Bun.spawn({\n\t\tcmd: [sshBin, ...sshArgs],\n\t\tstdin: \"inherit\",\n\t\tstdout: \"inherit\",\n\t\tstderr: \"inherit\",\n\t});\n\tconst exitCode = await proc.exited;\n\tif (exitCode !== 0) {\n\t\tthrow new Error(`ssh exited with code ${exitCode}`);\n\t}\n}\n\nasync function runLogout(flags: AuthBrokerCommandArgs[\"flags\"]): Promise<void> {\n\tlet providerArg = flags.provider;\n\tconst store = await SqliteAuthCredentialStore.open(getAgentDbPath());\n\ttry {\n\t\tif (!providerArg) {\n\t\t\tconst stored = store.listProviders();\n\t\t\tif (stored.length === 0) {\n\t\t\t\tprocess.stdout.write(\"No credentials stored.\\n\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tproviderArg = await pickStoredProviderInteractively(stored);\n\t\t}\n\t\tstore.deleteAuthCredentialsForProvider(providerArg, \"logged out by user\");\n\t\tprocess.stdout.write(`Logged out of ${providerArg}\\n`);\n\t} finally {","sourceCodeStart":386,"sourceCodeEnd":422,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/cli/auth-broker-cli.ts#L386-L422","documentation":"After spawning `ssh` with inherited stdio to establish the OAuth port-forward, `runRemoteLogin` awaits the process exit code and throws if it is non-zero. Any ssh failure (auth rejection, unreachable host, port bind conflict) is reported with the raw exit code, preserving the ssh diagnostics printed to the terminal.","triggerScenarios":"ssh exits non-zero during remote login: wrong host/user, key rejected or agent missing, local callback port already bound (`Address already in use`), host key verification failure, or network timeout.","commonSituations":"Another local process holding the forwarded port; stale `known_hosts` after server rebuild; expired SSH key/agent not running; typo in the `--via host` argument.","solutions":["Read the ssh diagnostics printed before the error and fix the specific failure (host, key, network).","Free the local callback port if already bound (`lsof -i :<port>`, then stop the holder).","Verify connectivity manually (`ssh <host> true`), resolve auth/host-key prompts, then re-run the login."],"exampleFix":"// before\nomp auth-broker login --via bastion   // ssh exited with code 255\n// after (verify ssh first)\nssh bastion true && omp auth-broker login --via bastion","handlingStrategy":"try-catch","validationCode":"// preflight: ssh connectivity and free local port\nawait $`ssh -o BatchMode=yes ${host} true`.quiet().nothrow();\nconst port = CALLBACK_PORTS[provider];\nconst inUse = await $`lsof -i :${port}`.quiet().nothrow();\nif (inUse.exitCode === 0) console.warn(`port ${port} already bound; stop the holder first`);","typeGuard":null,"tryCatchPattern":"try {\n  await runLogin({ provider, via: host });\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"ssh exited with code \")) {\n    const code = Number(err.message.match(/code (\\d+)/)?.[1]);\n    // 255 = ssh error (auth/host); see ssh(1) for other codes\n    console.error(`ssh failed (exit ${code}); fix host/key/port conflict and retry.`);\n  } else throw err;\n}","preventionTips":["Test `ssh <host>` manually before scripted remote logins.","Free the forwarded callback port (`lsof -i :<port>`) before re-running.","Use `ssh -o BatchMode=yes` checks in CI to fail fast on auth issues."],"tags":["ssh","network","process-exit"],"backgroundTag":"ssh-exit-code-nonzero","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}