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

  1. Fix the server to send X-Croc-Downloads: <requested positive integer> or omit it entirely
  2. Check for proxies (corporate gateways, devtools rewrite rules) corrupting the header
  3. 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

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


AI-assisted analysis of schollz/croc@e25f1bdc04 (2026-08-15). Data as JSON: /api/errors/c53d4bb729d9567d. Report an issue: GitHub.