can1357/oh-my-pi · error · Error
No response body
Error message
No response body
What it means
After a successful (ok) fetch, downloadFile() expects a streaming response body to write to the destination file. If response.body is null — which the fetch spec permits in rare cases even for OK responses — it throws this error rather than silently producing an empty file.
Source
Thrown at packages/coding-agent/src/utils/tools-manager.ts:206
throw new Error(`GitHub API error: ${response.status}`);
}
const data = (await response.json()) as { tag_name: string };
return data.tag_name.replace(/^v/, "");
}
/** Download a tool asset without handing the streaming Response to Bun.write. */
export async function downloadFile(url: string, dest: string, signal?: AbortSignal): Promise<void> {
const downloadSignal = ptree.combineSignals(signal, TOOL_DOWNLOAD_TIMEOUT_MS);
let response: Response;
try {
response = await fetch(url, {
signal: downloadSignal,
});
if (!response.ok) {
throw new Error(`Failed to download: ${response.status}`);
} else if (!response.body) {
throw new Error("No response body");
}
await writeResponseBody(dest, response.body, downloadSignal);
} catch (err) {
if (isAbortLikeError(err)) {
throw new Error(`Download timed out: ${url}`);
}
throw err;
}
}
// Download and install a tool
async function downloadTool(tool: ToolName, signal?: AbortSignal): Promise<string> {
const config = TOOLS[tool];
if (!config) throw new Error(`Unknown tool: ${tool}`);
const plat = os.platform();
const architecture = os.arch();
View on GitHub (pinned to 9690622007)
Solutions
- Retry the download — this is almost always a transient or network-middlebox artifact, not a code bug.
- Disable or bypass proxies/VPNs/security appliances that may rewrite the HTTP response.
- Verify with curl that the asset URL returns a real body (curl -I to check Content-Length).
- If reproducible behind a specific proxy, download the asset manually and place it in the tools directory.
Defensive patterns
Strategy: retry
Validate before calling
// pre-flight: confirm the URL serves a body | const head = await fetch(assetUrl, { method: "HEAD" }); if (!head.ok || head.headers.get("content-length") === "0") throw new Error("Asset has no body"); Type guard
function isEmptyBodyError(err: unknown): err is Error { return err instanceof Error && err.message === "No response body"; } Try / catch
try { const p = await toolsManager.download("sg"); } catch (err) { if (isEmptyBodyError(err)) { await Bun.sleep(2000); /* transient middlebox artifact; retry */ } else throw err; } Prevention
- Retry — this error is almost always transient.
- Bypass proxies/security appliances when downloading release assets.
- Verify asset URLs with curl -I when debugging.
- Report persistent occurrences with proxy/network details.
When it happens
Trigger: The asset fetch returned response.ok === true but response.body === null, so writeResponseBody cannot be called and downloadFile throws "No response body".
Common situations: Unusual proxy or middleware stripping/terminating the body, non-standard HTTP responses intercepted by network appliances, or a corrupted/edge-case response from GitHub's CDN.
Related errors
- AnthropicConnectionError
- AnthropicConnectionTimeoutError
- xAI device-code request failed: ${error instanceof Error ? e
- Failed to fetch Umans models info
- Gemini Files API delete request failed
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/eb43e2ea797f1a27.
Report an issue: GitHub.