can1357/oh-my-pi · error · ArchiveError
Remote archive request failed
Error message
Remote archive request failed (HTTP ${probe.status}) What it means
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.
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
Example fix
// before: bare URL fails with 403 on a private bucket
const src = await httpByteSource("https://s3.example/private.tar");
// after: supply auth headers
const src = await httpByteSource("https://s3.example/private.tar", {
headers: { authorization: `Bearer ${token}` },
}); Defensive patterns
Strategy: retry
Validate before calling
const probe = await fetch(url, { method: "HEAD", headers });
if (!probe.ok) throw new Error(`archive URL unreachable: HTTP ${probe.status}`); Try / catch
try {
const src = await httpByteSource(url, { headers });
} catch (err) {
if (err instanceof ArchiveError && /HTTP \d+/.test(err.message)) {
const status = Number(/HTTP (\d+)/.exec(err.message)?.[1]);
if (status === 429 || status >= 500) return retryWithBackoff();
if (status === 401 || status === 403) return refreshCredentialsAndRetry();
throw new Error(`archive unavailable (HTTP ${status}); check URL and auth`, { cause: err });
}
throw err;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Remote archive range request failed
- Auth broker returned no initial snapshot
- Auth broker returned no snapshot
- bridge call # : non-JSON response: #
- bridge call : non-JSON response
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/f75bbbc83b9c03fe.
Report an issue: GitHub.
Appendix: source
Thrown at packages/utils/src/ar/source.ts:108
const probe = await doFetch(url, { headers });
if (probe.status === 200) {
// No range support: buffer the whole body once, bounded.
const cap = options.maxFallbackBytes ?? HTTP_FALLBACK_CAP;
const declared = Number(probe.headers.get("content-length") ?? 0);
if (declared > cap) {
throw new ArchiveError(
`Remote archive is too large to buffer without range support (${declared} > ${cap} bytes)`,
);
}
const bytes = new Uint8Array(await probe.arrayBuffer());
if (bytes.byteLength > cap) {
throw new ArchiveError(`Remote archive is too large to buffer without range support (> ${cap} bytes)`);
}
return memoryByteSource(bytes);
}
if (probe.status !== 206) {
await probe.body?.cancel();
throw new ArchiveError(`Remote archive request failed (HTTP ${probe.status})`);
}
await probe.body?.cancel();
// `Content-Range: bytes 0-0/12345` carries the total size.
const contentRange = probe.headers.get("content-range");
const total = contentRange ? Number(/\/(\d+)$/.exec(contentRange)?.[1]) : Number.NaN;
if (!Number.isSafeInteger(total) || total < 0) {
throw new ArchiveError("Remote archive did not report a valid size in Content-Range");
}
return {
size: total,
async read(start, end) {
assertValidRange(start, end);
if (start === end) return new Uint8Array(0);
const response = await doFetch(url, {
headers: { ...options.headers, range: `bytes=${start}-${end - 1}` },
});
if (response.status !== 206) {
await response.body?.cancel();View on GitHub (pinned to 9690622007)