can1357/oh-my-pi · error · Error
${argv[0]} exited with code ${exitCode}: ${stderr.trim().sli
Error message
${argv[0]} exited with code ${exitCode}: ${stderr.trim().slice(-300)} What it means
The command uploader spawns the configured upload program and captures stdout, stderr, and the exit code. If the program exits with a nonzero code, the error surfaces the program name, exit code, and the last 300 characters of stderr. This propagates the external tool's own failure rather than hiding it.
Source
Thrown at packages/coding-agent/src/blob-broker/uploaders.ts:109
await Bun.write(file, bytes);
try {
const argv = argvTemplate.map(arg =>
arg.replaceAll("{file}", file).replaceAll("{mime}", mimeType).replaceAll("{ext}", extension),
);
const cwd = getProjectDir();
if (!directoryIsEnterableSync(cwd)) {
throw new Error(`Project directory is not accessible: ${cwd}`);
}
const proc = Bun.spawn(argv, { stdin: "ignore", stdout: "pipe", stderr: "pipe", cwd });
const timeout = setTimeout(() => proc.kill(), UPLOAD_TIMEOUT_MS);
const [stdout, stderr, exitCode] = await Promise.all([
new Response(proc.stdout as ReadableStream<Uint8Array>).text(),
new Response(proc.stderr as ReadableStream<Uint8Array>).text(),
proc.exited,
]);
clearTimeout(timeout);
if (exitCode !== 0) {
throw new Error(`${argv[0]} exited with code ${exitCode}: ${stderr.trim().slice(-300)}`);
}
const url = extractUploadUrl(stdout);
if (!url) throw new Error(`${argv[0]} printed no URL on stdout`);
return { url, destination: "command", bytes: bytes.byteLength };
} finally {
await fs.rm(file, { force: true });
}
},
};
}
/**
* Resolve one registry destination to its built-in uploader.
*
* Serving destinations deliberately return `null`; the broker selects those
* through its separate serve-kind predicate. Registry entries known to be
* unusable, and active entries without an implementation, fail explicitly
* before an upload can issue a network request.View on GitHub (pinned to 9690622007)
Solutions
- Read the stderr tail in the error message — it contains the tool's own diagnostic
- Run the command manually with a test file, substituting the path for {file}, to reproduce
- Check/rotate credentials or tokens for the upload service
- Increase headroom for the timeout (upload smaller files / faster network) or verify flag syntax after placeholder substitution
Example fix
// before
"urls": { "command": "curl -F file={file} https://0x0.st" } // shell parses {file} oddly
// after
"urls": { "command": "curl -sF 'file=@{file}' https://0x0.st" } Defensive patterns
Strategy: try-catch
Validate before calling
// dry-run the command template before wiring it:
const argv = template.split(" ").map(a => a.replaceAll("{file}", "/tmp/test.png"));
const proc = Bun.spawn(argv, { stdout: "pipe", stderr: "pipe" });
if ((await proc.exited) !== 0) console.error("upload command fails outside the broker too"); Try / catch
try {
await uploader.upload(req);
} catch (err) {
if (err instanceof Error && /exited with code/.test(err.message)) {
// read the stderr tail embedded in the message for the tool's own diagnostic
}
throw err;
} Prevention
- Test the command manually with a file substituted for {file}
- Keep service credentials/tokens valid and rotated
- Match flag syntax exactly after placeholder substitution
- Watch for timeout kills on large uploads or slow networks
When it happens
Trigger: The configured images.urls.command program fails for any reason: bad credentials, network failure, invalid flags (often because {file}/{mime}/{ext} substitution produces an unexpected argument), server rejection of the upload (4xx/5xx), or the program being killed by UPLOAD_TIMEOUT_MS timeout (proc.kill).
Common situations: Expired or wrong upload-service API token; the placeholder-substituted arguments don't match the tool's CLI syntax; rate limiting or file-size limits on the target service; a slow network hitting the upload timeout and killing the process.
Related errors
- ${argv[0]} printed no URL on stdout
- Process exited with code ${exitCode}: ${stderr}
- Full stderr capture must be requested when spawning the proc
- RPC process stopped before ready: {error}. Stderr: {stderr}
- str(self._closed_error)
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/2ca53c0c14e1833c.
Report an issue: GitHub.