schollz/croc · error
Storage service returned an invalid download count
Error message
Storage service returned an invalid download count
What it means
After creation, the client reads the X-Croc-Downloads response header to learn how many downloads the server actually granted; the value must be an integer >= 1 (a missing header defaults to 1). A non-numeric, fractional, zero, or negative value throws, because the download budget drives claim/commit accounting.
Source
Thrown at web/src/protocol/stored.ts:451
const created = (await response.json()) as {
id: string;
uploadToken: string;
uploadExpiresAt: string;
chunkSize: number;
};
if (created.chunkSize !== storedChunkSize) {
throw new Error(
`Storage service returned unsupported chunk size ${created.chunkSize}`,
);
}
if (!isCapability(created.uploadToken)) {
throw new Error("Storage service returned an invalid upload capability");
}
const downloadsHeader = response.headers.get("X-Croc-Downloads");
const acceptedDownloads =
downloadsHeader === null ? 1 : Number(downloadsHeader);
if (!Number.isSafeInteger(acceptedDownloads) || acceptedDownloads < 1) {
throw new Error("Storage service returned an invalid download count");
}
if (acceptedDownloads !== downloads) {
throw new Error(
`Storage service created ${acceptedDownloads} downloads instead of ${downloads}`,
);
}
return {
share: validateShare({
origin: window.location.origin,
id: created.id,
key,
}),
uploadToken: created.uploadToken,
};
}
async function uploadStoredManifest(
plan: StoredUploadPlan,View on GitHub (pinned to e25f1bdc04)
Solutions
- Fix the server to send X-Croc-Downloads: <requested positive integer> or omit it entirely
- Check for proxies (corporate gateways, devtools rewrite rules) corrupting the header
- Retry against a known-good deployment to confirm it is a server-side contract violation
Defensive patterns
Strategy: try-catch
Try / catch
try { return await createStoredUpload(...); } catch (e) { if (e instanceof Error && e.message.includes("invalid download count")) { logServerContractViolation("X-Croc-Downloads"); } throw e; } Prevention
- Ensure the server sends X-Croc-Downloads as a positive integer or omits it (defaults to 1)
- Keep header-rewriting proxies off the storeAPI path
When it happens
Trigger: The create response's X-Croc-Downloads header is e.g. "0", "1.5", "many", or garbage — a misimplemented server, or an HTTP/1.0-style proxy that drops or mangles headers (dropped header is fine: it defaults to 1; a corrupted one throws).
Common situations: Self-hosted services that clamp downloads to 0 when storage is tight; debugging proxies rewriting headers; custom server implementations that never set the header but also use a default other than 1.
Related errors
- Storage service created ${acceptedDownloads} downloads inste
- Invalid stored-transfer id
- Stored transfers can contain at most ${settings.maxFiles} fi
- Stored transfer exceeds the ${settings.maxTransferBytes} byt
- Duplicate filename: ${name}
AI-assisted analysis of schollz/croc@e25f1bdc04 (2026-08-15).
Data as JSON: /api/errors/c53d4bb729d9567d.
Report an issue: GitHub.