{"record":{"id":"dcb9aec768bee149","repo":"yamadashy/repomix","slug":"no-response-body-received","errorCode":null,"errorMessage":"No response body received","messagePattern":"No response body received","errorType":"exception","errorClass":"RepomixError","httpStatus":null,"severity":"error","filePath":"src/core/git/gitHubArchive.ts","lineNumber":129,"sourceCode":"const downloadAndExtractArchive = async (\n  archiveUrl: string,\n  targetDirectory: string,\n  timeout: number,\n  onProgress?: ProgressCallback,\n  deps: ArchiveDownloadDeps = defaultDeps,\n): Promise<void> => {\n  const controller = new AbortController();\n  const timeoutId = setTimeout(controller.abort.bind(controller), timeout);\n\n  try {\n    const response = await deps.fetch(archiveUrl, {\n      signal: controller.signal,\n    });\n\n    checkGitHubResponse(response);\n\n    if (!response.body) {\n      throw new RepomixError('No response body received');\n    }\n\n    const totalSize = response.headers.get('content-length');\n    const total = totalSize ? Number.parseInt(totalSize, 10) : null;\n    let downloaded = 0;\n    let lastProgressUpdate = 0;\n\n    const nodeStream = Readable.fromWeb(response.body as import('node:stream/web').ReadableStream);\n\n    // Transform stream for progress tracking\n    const progressStream = new deps.Transform({\n      transform(chunk, _encoding, callback) {\n        downloaded += chunk.length;\n\n        // Update progress at most every 100ms to avoid too frequent updates\n        const now = Date.now();\n        if (onProgress && now - lastProgressUpdate > 100) {\n          lastProgressUpdate = now;","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/yamadashy/repomix/blob/f465ad909315a22120636baf03fa5e28701a50cb/src/core/git/gitHubArchive.ts#L111-L147","documentation":"After fetching the GitHub archive response, the code checks response.ok (via checkGitHubResponse) and then requires a non-null response.body to stream the tar.gz. A 2xx response with a null body is treated as fatal because there is nothing to download or extract.","triggerScenarios":"fetch() resolves with an OK status but response.body is null — seen with some runtimes/proxies that return empty-bodied 2xx responses, an abort signal firing mid-setup, or an intermediary cache returning an empty 200.","commonSituations":"Corporate proxies or security appliances stripping response bodies; unusual fetch polyfills/undici configurations in CI; GitHub returning an empty 200 behind a broken cache layer.","solutions":["Simply retry — the failure is usually transient; downloadGitHubArchive's retry loop will re-attempt.","Inspect the response through your proxy/AV appliance; disable body-stripping or add an exception for codeload.github.com.","Check that no AbortSignal/timeout is cancelling the request immediately, and that the runtime's fetch implementation supports streaming bodies (Node >= 18 native fetch).","Fall back to `git clone` of the repository and run repomix on the local directory."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await pack({ remote: url });\n} catch (e) {\n  if (e instanceof RepomixError && e.message === 'No response body received') {\n    // transient/empty 2xx: retry with backoff\n    await new Promise(r => setTimeout(r, 3000));\n  } else throw e;\n}","preventionTips":["Disable proxy/AV features that strip or cache-empty response bodies for github.com/codeload.github.com.","Use Node >= 18 native fetch (full streaming-body support).","Rely on the library's retry loop instead of wrapping calls in single-shot logic."],"tags":["network","github","streaming","empty-response"],"backgroundTag":"empty-response-body","analyzedSha":"f465ad909315a22120636baf03fa5e28701a50cb","analyzedAt":"2026-08-29T01:27:42.024Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}