can1357/oh-my-pi · error · NonZeroExitError
Process exited with code ${exitCode}: ${stderr}
Error message
Process exited with code ${exitCode}:
${stderr} What it means
NonZeroExitError is thrown by the `exitedCleanly` getter when a managed subprocess terminates with a non-zero exit code and the process was not spawned with nothrow semantics. The message includes the exit code and a truncated stderr tail (last 32KB) so the caller can see why the child failed.
Source
Thrown at packages/utils/src/ptree.ts:321
}
get stdin(): Bun.SpawnOptions.WritableToIO<In> {
return this.proc.stdin;
}
/** Raw stdout stream. Must be consumed to prevent pipe deadlock. */
get stdout() {
return this.proc.stdout;
}
/** Optional stderr stream (only when requested in spawn options). */
get stderr() {
return this.#stderrStream;
}
get exitedCleanly(): Promise<number> {
if (this.#nothrow) return this.#exited;
return this.#exited.then(code => {
if (code !== 0) throw new NonZeroExitError(code, this.#stderrTail);
return code;
});
}
/** Returns the truncated stderr tail (last 32KB). */
peekStderr() {
return this.#stderrTail;
}
nothrow(): this {
this.#nothrow = true;
return this;
}
kill(reason?: Exception, gracefulMs?: number) {
if (reason && !this.#exitReasonPending) {
this.#exitReasonPending = reason;
// The normalized exit promise may already have resolved from a deadView on GitHub (pinned to 9690622007)
Solutions
- Read the stderr tail in the error message to find the child's actual failure.
- Fix the underlying command or its arguments/inputs.
- If non-zero exit is acceptable, construct the process with nothrow (or use `.exited` directly) instead of `exitedCleanly`.
- Wrap in try/catch and handle NonZeroExitError when failure is expected.
Example fix
// before
await proc.exitedCleanly;
// after
try {
await proc.exitedCleanly;
} catch (err) {
console.error(err.message); // includes code + stderr tail
} Defensive patterns
Strategy: try-catch
Type guard
function isNonZeroExitError(err: unknown): err is { code: number; stderrTail?: string } {
return err instanceof Error && /Process exited with code \d+/.test(err.message);
} Try / catch
try {
await proc.exitedCleanly;
} catch (err) {
if (/Process exited with code/.test(err.message)) {
logger.error('child failed', { stderr: err.message });
} else throw err;
} Prevention
- Check exit codes of every spawned command instead of assuming success.
- Use nothrow construction when non-zero exit is an expected branch.
- Include the stderr tail in logs when reporting child failures.
When it happens
Trigger: Awaiting `process.exitedCleanly` on any PTree-managed subprocess that exits with code != 0 — e.g. a build step returning 1, a shell command hitting a missing binary (127), or a killed process (signal-derived codes).
Common situations: Running git/jj or package-manager commands via execText/captureText helpers where the command fails; scripts assuming success; flaky network commands.
Related errors
- ${argv[0]} exited with code ${exitCode}: ${stderr.trim().sli
- Full stderr capture must be requested when spawning the proc
- ${argv[0]} printed no URL on stdout
- ${(result.stderr || result.stdout).replace(/\s+/g, " ").trim
- VHS failed to render the gallery screenshot${detail ? `: ${d
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/b0d57647a710f6f1.
Report an issue: GitHub.