{"record":{"id":"2ca53c0c14e1833c","repo":"can1357/oh-my-pi","slug":"argv-0-exited-with-code-exitcode-stderr","errorCode":null,"errorMessage":"${argv[0]} exited with code ${exitCode}: ${stderr.trim().slice(-300)}","messagePattern":"(.+?) exited with code (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/blob-broker/uploaders.ts","lineNumber":109,"sourceCode":"\t\t\tawait Bun.write(file, bytes);\n\t\t\ttry {\n\t\t\t\tconst argv = argvTemplate.map(arg =>\n\t\t\t\t\targ.replaceAll(\"{file}\", file).replaceAll(\"{mime}\", mimeType).replaceAll(\"{ext}\", extension),\n\t\t\t\t);\n\t\t\t\tconst cwd = getProjectDir();\n\t\t\t\tif (!directoryIsEnterableSync(cwd)) {\n\t\t\t\t\tthrow new Error(`Project directory is not accessible: ${cwd}`);\n\t\t\t\t}\n\t\t\t\tconst proc = Bun.spawn(argv, { stdin: \"ignore\", stdout: \"pipe\", stderr: \"pipe\", cwd });\n\t\t\t\tconst timeout = setTimeout(() => proc.kill(), UPLOAD_TIMEOUT_MS);\n\t\t\t\tconst [stdout, stderr, exitCode] = await Promise.all([\n\t\t\t\t\tnew Response(proc.stdout as ReadableStream<Uint8Array>).text(),\n\t\t\t\t\tnew Response(proc.stderr as ReadableStream<Uint8Array>).text(),\n\t\t\t\t\tproc.exited,\n\t\t\t\t]);\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\tif (exitCode !== 0) {\n\t\t\t\t\tthrow new Error(`${argv[0]} exited with code ${exitCode}: ${stderr.trim().slice(-300)}`);\n\t\t\t\t}\n\t\t\t\tconst url = extractUploadUrl(stdout);\n\t\t\t\tif (!url) throw new Error(`${argv[0]} printed no URL on stdout`);\n\t\t\t\treturn { url, destination: \"command\", bytes: bytes.byteLength };\n\t\t\t} finally {\n\t\t\t\tawait fs.rm(file, { force: true });\n\t\t\t}\n\t\t},\n\t};\n}\n\n/**\n * Resolve one registry destination to its built-in uploader.\n *\n * Serving destinations deliberately return `null`; the broker selects those\n * through its separate serve-kind predicate. Registry entries known to be\n * unusable, and active entries without an implementation, fail explicitly\n * before an upload can issue a network request.","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/blob-broker/uploaders.ts#L91-L127","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\n\"urls\": { \"command\": \"curl -F file={file} https://0x0.st\" }  // shell parses {file} oddly\n// after\n\"urls\": { \"command\": \"curl -sF 'file=@{file}' https://0x0.st\" }","handlingStrategy":"try-catch","validationCode":"// dry-run the command template before wiring it:\nconst argv = template.split(\" \").map(a => a.replaceAll(\"{file}\", \"/tmp/test.png\"));\nconst proc = Bun.spawn(argv, { stdout: \"pipe\", stderr: \"pipe\" });\nif ((await proc.exited) !== 0) console.error(\"upload command fails outside the broker too\");","typeGuard":null,"tryCatchPattern":"try {\n\tawait uploader.upload(req);\n} catch (err) {\n\tif (err instanceof Error && /exited with code/.test(err.message)) {\n\t\t// read the stderr tail embedded in the message for the tool's own diagnostic\n\t}\n\tthrow err;\n}","preventionTips":["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"],"tags":["process-exit","command-uploader","subprocess","stderr"],"backgroundTag":"nonzero-exit-code","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}