{"record":{"id":"f75bbbc83b9c03fe","repo":"can1357/oh-my-pi","slug":"remote-archive-request-failed-http-probe-status","errorCode":null,"errorMessage":"Remote archive request failed (HTTP ${probe.status})","messagePattern":"Remote archive request failed \\(HTTP (.+?)\\)","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/source.ts","lineNumber":108,"sourceCode":"\tconst probe = await doFetch(url, { headers });\n\tif (probe.status === 200) {\n\t\t// No range support: buffer the whole body once, bounded.\n\t\tconst cap = options.maxFallbackBytes ?? HTTP_FALLBACK_CAP;\n\t\tconst declared = Number(probe.headers.get(\"content-length\") ?? 0);\n\t\tif (declared > cap) {\n\t\t\tthrow new ArchiveError(\n\t\t\t\t`Remote archive is too large to buffer without range support (${declared} > ${cap} bytes)`,\n\t\t\t);\n\t\t}\n\t\tconst bytes = new Uint8Array(await probe.arrayBuffer());\n\t\tif (bytes.byteLength > cap) {\n\t\t\tthrow new ArchiveError(`Remote archive is too large to buffer without range support (> ${cap} bytes)`);\n\t\t}\n\t\treturn memoryByteSource(bytes);\n\t}\n\tif (probe.status !== 206) {\n\t\tawait probe.body?.cancel();\n\t\tthrow new ArchiveError(`Remote archive request failed (HTTP ${probe.status})`);\n\t}\n\tawait probe.body?.cancel();\n\t// `Content-Range: bytes 0-0/12345` carries the total size.\n\tconst contentRange = probe.headers.get(\"content-range\");\n\tconst total = contentRange ? Number(/\\/(\\d+)$/.exec(contentRange)?.[1]) : Number.NaN;\n\tif (!Number.isSafeInteger(total) || total < 0) {\n\t\tthrow new ArchiveError(\"Remote archive did not report a valid size in Content-Range\");\n\t}\n\treturn {\n\t\tsize: total,\n\t\tasync read(start, end) {\n\t\t\tassertValidRange(start, end);\n\t\t\tif (start === end) return new Uint8Array(0);\n\t\t\tconst response = await doFetch(url, {\n\t\t\t\theaders: { ...options.headers, range: `bytes=${start}-${end - 1}` },\n\t\t\t});\n\t\t\tif (response.status !== 206) {\n\t\t\t\tawait response.body?.cancel();","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/source.ts#L90-L126","documentation":"httpByteSource() probes the remote archive with a Range request and expects either 200 (no range support, full-body fallback) or 206 (range support). Any other status — 403, 404, 500, 416, redirects handled as errors, etc. — is rejected with this ArchiveError and the response body is cancelled. It is the generic 'the HTTP probe did not succeed' guard at the start of remote archive access.","triggerScenarios":"Calling httpByteSource(url) where the probe request returns a status other than 200 or 206: expired/missing auth (401/403), wrong URL (404), server error (5xx), presigned URL expiration, or a 416 from a server that mis-handles the Range header.","commonSituations":"Stale or revoked S3 presigned URLs (403); archives moved or deleted after a manifest was generated (404); corporate proxies blocking the host (407/502); rate limiting (429); pointing at an API endpoint instead of the raw file.","solutions":["Log/inspect the HTTP status in the message and fix the URL or credentials accordingly (401/403 → auth, 404 → path, 5xx → server)","Pass authorization headers via httpByteSource(url, { headers: { authorization: 'Bearer ...' } }) if the archive requires auth","Refresh or regenerate presigned/expired URLs immediately before calling httpByteSource","Retry with backoff for transient 5xx/429 statuses; fail fast on 4xx"],"exampleFix":"// before: bare URL fails with 403 on a private bucket\nconst src = await httpByteSource(\"https://s3.example/private.tar\");\n// after: supply auth headers\nconst src = await httpByteSource(\"https://s3.example/private.tar\", {\n\theaders: { authorization: `Bearer ${token}` },\n});","handlingStrategy":"retry","validationCode":"const probe = await fetch(url, { method: \"HEAD\", headers });\nif (!probe.ok) throw new Error(`archive URL unreachable: HTTP ${probe.status}`);","typeGuard":null,"tryCatchPattern":"try {\n\tconst src = await httpByteSource(url, { headers });\n} catch (err) {\n\tif (err instanceof ArchiveError && /HTTP \\d+/.test(err.message)) {\n\t\tconst status = Number(/HTTP (\\d+)/.exec(err.message)?.[1]);\n\t\tif (status === 429 || status >= 500) return retryWithBackoff();\n\t\tif (status === 401 || status === 403) return refreshCredentialsAndRetry();\n\t\tthrow new Error(`archive unavailable (HTTP ${status}); check URL and auth`, { cause: err });\n\t}\n\tthrow err;\n}","preventionTips":["Verify the URL with a HEAD request (or curl -I) before wiring it into archive reads","Pass auth headers through HttpByteSourceOptions.headers instead of relying on ambient cookies","Regenerate presigned URLs at session start and again on 403 during long jobs","Handle 429/5xx with exponential backoff; fail fast on 4xx client errors"],"tags":["http","network","remote-archive","http-status"],"backgroundTag":"http-request-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}