can1357/oh-my-pi · error · Error
Claude command exited before /v1/messages completed${outputS
Error message
Claude command exited before /v1/messages completed${outputSuffix()} What it means
The fallback case of the capture race: the Claude command exited (without an error object) before any /v1/messages exchange was captured, and even after the 250ms late-capture grace window no exchange arrived. The trace throws with any captured output appended so the developer can see why Claude quit.
Source
Thrown at packages/coding-agent/src/cli/claude-trace-cli.ts:781
const first = await Promise.race([captureRace, ptyRace]);
if (first.kind === "capture") {
await shutdownPty(session, runPromise);
return first.exchange;
}
if (first.kind === "capture-error") {
throw new Error(`${errorMessage(first.error)}${outputSuffix()}`);
}
const late = await Promise.race([captureRace, Bun.sleep(250).then(() => ({ kind: "late-timeout" as const }))]);
if (late.kind === "capture") {
await shutdownPty(session, runPromise);
return late.exchange;
}
if (first.kind === "pty-error") {
throw new Error(
`Claude command failed before /v1/messages completed: ${errorMessage(first.error)}${outputSuffix()}`,
);
}
throw new Error(`Claude command exited before /v1/messages completed${outputSuffix()}`);
} finally {
terminal.dispose();
await proxy.stop();
}
}
export async function runClaudeTraceCommand(args: ClaudeTraceCommandArgs = {}): Promise<void> {
process.stderr.write(
`Starting Claude trace proxy on ${args.host ?? DEFAULT_PROXY_HOST}:${args.port ?? DEFAULT_PROXY_PORT}\n`,
);
const exchange = await runClaudeMessagesCapture(args);
const output = args.json ? `${JSON.stringify(exchange, null, 2)}\n` : formatCapturedMessagesExchange(exchange);
process.stdout.write(output.endsWith("\n") ? output : `${output}\n`);
}
View on GitHub (pinned to 9690622007)
Solutions
- Read the outputSuffix() capture output included in the message — it shows what claude printed before exiting.
- Run `claude -p 'hi'` manually to see the early exit (help text, TOS prompt, auth wall) and fix it.
- Increase --input-delay so the prompt is typed after claude fully initializes.
- Re-run the trace; if the capture keeps missing fast exchanges, check proxy/TLS setup so the exchange is recorded on time.
Example fix
// before: claude exits showing onboarding prompt $ omp claude-trace // after: pre-accept onboarding, then trace $ claude # complete onboarding once $ omp claude-trace
Defensive patterns
Strategy: validation
Validate before calling
const check = await Bun.$`claude --version`.quiet().nothrow();
if (check.exitCode !== 0) throw new Error("claude CLI missing or failing at startup"); Try / catch
try {
const exchange = await runTrace();
} catch (err) {
if ((err as Error).message.includes("exited before /v1/messages completed")) {
// inspect the captured output appended to the message for claude's final output
} else throw err;
} Prevention
- Complete claude onboarding/TOS interactively once before tracing
- Raise --input-delay so the prompt is typed only after claude fully initializes
- Read the captured output in the error message first — it usually names the early-exit reason
When it happens
Trigger: The PTY session observes claude exiting normally-but-early (exit event, not an error throw) with no /v1/messages capture completing — e.g. claude exited instantly, rejected the prompt interactively, or the session ended before the API call.
Common situations: claude CLI printed a usage/help screen and exited; interactive confirmation or TOS-acceptance prompt stalled then exited; extremely fast failure where pty-error vs exit classification landed on the exit branch; network so fast the capture missed the exchange (rare).
Related errors
- Claude command failed before /v1/messages completed: ${error
- cli_message(command, exit_code, stdout, stderr)
- ${argv[0]} exited with code ${exitCode} before reporting a t
- ssh reverse forward to ${config.sshTarget} exited with code
- ${argv[0]} exited with code ${exitCode}: ${stderr.trim().sli
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/1560c6ce3bef5827.
Report an issue: GitHub.