schollz/croc · error

Storage service returned an invalid claim capability

Error message

Storage service returned an invalid claim capability

What it means

Thrown after POST /{share.id}/claim: the HTTP request succeeded but the JSON body's claimToken failed the isCapability() format check (stored.ts:118). The claim token is a capability string authorizing subsequent downloads; rejecting a malformed one up front prevents confusing failures later in the download flow.

Source

Thrown at web/src/protocol/stored.ts:749

  inspection: StoredInspection,
  settings: StoredSettings,
  signal?: AbortSignal,
) {
  try {
    const existing = sessionStorage.getItem(claimSessionKey(inspection.share.id));
    if (existing) return existing;
  } catch {
    // Session persistence is optional.
  }
  const redeem = await wasm().storeRedeemCapability(inspection.share.key);
  const response = await authorizedFetch(
    api(settings, `/${inspection.share.id}/claim`),
    base64URL(redeem),
    { method: "POST", signal },
  );
  const claimed = (await response.json()) as { claimToken: string };
  if (!isCapability(claimed.claimToken)) {
    throw new Error("Storage service returned an invalid claim capability");
  }
  try {
    sessionStorage.setItem(claimSessionKey(inspection.share.id), claimed.claimToken);
  } catch {
    // The claim remains valid in memory.
  }
  return claimed.claimToken;
}

type StoredReceiveSession = {
  inspection: StoredInspection;
  settings: StoredSettings;
  callbacks: ReceiveCallbacks;
  signal?: AbortSignal;
  claimToken: string;
  totalBytes: number;
};

View on GitHub (pinned to e25f1bdc04)

Solutions

  1. Verify service and web client versions match (endpoint must return { claimToken: <capability> })
  2. Hard-refresh / cache-bust the web bundle after a service upgrade
  3. Check that intermediaries (proxy/CDN) pass response bodies through unmodified
  4. If you operate the server, log the actual claim response and align field names
Defensive patterns

Strategy: try-catch

Type guard

function isClaimResponse(v: unknown): v is { claimToken: string } {
  const r = v as Record<string, unknown>;
  return typeof r?.claimToken === 'string' && r.claimToken.length > 0;
}

Try / catch

try { await receiveStoredTransfer(others); } catch (e) { if (e instanceof Error && e.message === 'Storage service returned an invalid claim capability') { reportServiceVersionMismatch(); return; } throw e; }

Prevention

When it happens

Trigger: claimStored() gets a 2xx whose parsed body has claimToken undefined, empty, or not a valid base64URL capability. Causes: service version mismatch changing the response shape (e.g. `token` vs `claimToken`), a proxy rewriting the body, or a server bug.

Common situations: Storage service upgraded with a new claim schema while the browser runs a cached old web bundle; API gateway/CDN mangling JSON; pointing the web app at an incompatible or mocked backend.

Related errors


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