{"record":{"id":"7e881647f0cae9bc","repo":"can1357/oh-my-pi","slug":"download-failed-response-statustext","errorCode":null,"errorMessage":"Download failed: ${response.statusText}","messagePattern":"Download failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/cli/update-cli.ts","lineNumber":312,"sourceCode":"export async function downloadVerifiedBinary(options: VerifiedBinaryDownloadOptions): Promise<void> {\n\tconst fetchImpl = options.fetchImpl ?? fetch;\n\tawait unlinkIfExists(options.targetPath);\n\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetchImpl(options.url, {\n\t\t\tredirect: \"follow\",\n\t\t\tsignal: withTimeoutSignal(BINARY_DOWNLOAD_TIMEOUT_MS),\n\t\t});\n\t} catch (err) {\n\t\tif (isTimeoutError(err)) {\n\t\t\tthrow new Error(\"Timed out downloading release binary after 15 minutes\", { cause: err });\n\t\t}\n\t\tif (isUnsupportedProxyError(err)) throw new Error(unsupportedProxyMessage(), { cause: err });\n\t\tthrow err;\n\t}\n\tif (!response.ok || !response.body) {\n\t\tthrow new Error(`Download failed: ${response.statusText}`);\n\t}\n\n\tconst hash = createHash(\"sha256\");\n\tlet size = 0;\n\tconst verifier = new Transform({\n\t\ttransform(chunk, _encoding, callback) {\n\t\t\tsize += chunk.byteLength;\n\t\t\tif (size > options.expectedSize) {\n\t\t\t\tcallback(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`Downloaded binary size mismatch: expected ${options.expectedSize} bytes, received at least ${size}`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\thash.update(chunk);\n\t\t\tcallback(null, chunk);\n\t\t},","sourceCodeStart":294,"sourceCodeEnd":330,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/cli/update-cli.ts#L294-L330","documentation":"Thrown by downloadVerifiedBinary when the binary download response is either not ok (non-2xx after redirects) or has no body. The updater cannot stream a file to disk without a response body, and any non-2xx status means the asset was not delivered. The statusText is included for diagnosis.","triggerScenarios":"The release asset URL returns 404 (asset removed or tag deleted), 403 (asset marked private / download quota), or 5xx from the CDN; or response.body is null despite a 2xx (rare opaque/redirect edge case).","commonSituations":"A canary release was deleted moments after metadata was fetched; GitHub's release-assets CDN returning transient 5xx; a proxy intercepting and stripping the body; repository made private between metadata fetch and download.","solutions":["Retry the update — CDN 5xx errors are usually transient.","Verify the asset URL exists by opening it (or `curl -I`) — if 404, wait for the release to be (re)published.","Bypass suspicious proxies with `env -u HTTPS_PROXY omp update` to rule out body-stripping middleboxes.","Install manually from the GitHub releases page if the asset is persistently unavailable."],"exampleFix":"// before: corporate proxy strips response bodies\n$ HTTPS_PROXY=http://corpx-proxy:3128 omp update\n// Error: Download failed: \n// after: bypass proxy for github\n$ env -u HTTPS_PROXY omp update","handlingStrategy":"retry","validationCode":"const head = await fetch(assetUrl, { method: \"HEAD\" });\nif (!head.ok) throw new Error(`Asset unavailable: ${head.status}; fix release/channel before updating`);","typeGuard":"function isDownloadFailed(err: unknown): boolean {\n  return err instanceof Error && err.message.startsWith(\"Download failed:\");\n}","tryCatchPattern":"try {\n  await runUpdate();\n} catch (err) {\n  if (isDownloadFailed(err) && /5\\d\\d| /.test(err.message)) {\n    await Bun.sleep(10_000);\n    return runUpdate(); // transient CDN error\n  }\n  throw err;\n}","preventionTips":["Verify the target release exists before scripted updates","Bypass intercepting proxies for github.com downloads","Retry transient 5xx automatically with backoff"],"tags":["network","http-error","download","update-cli"],"backgroundTag":"http-request-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}