schollz/croc · error
Stored transfers can expire after at most ${settings.maxExpi
Error message
Stored transfers can expire after at most ${settings.maxExpiresSeconds} seconds What it means
Thrown by uploadStoredFiles() (stored.ts:592) when expiresSeconds exceeds settings.maxExpiresSeconds, the per-deployment expiry cap advertised by the storage service. maxExpiresSeconds of 0 means unlimited (the check is skipped); any positive value is a hard ceiling. The web app already mins this runtime value against the ~292-year absolute limit in App.tsx and feeds it to the expiration picker.
Source
Thrown at web/src/protocol/stored.ts:596
if (downloads > settings.maxDownloads) {
throw new Error(
`Stored transfers can allow at most ${settings.maxDownloads} downloads`,
);
}
if (
!Number.isSafeInteger(expiresSeconds) ||
expiresSeconds < 60 ||
expiresSeconds > 9_223_372_036
) {
throw new Error(
"Stored-transfer expiration must be a whole number of seconds of at least one minute",
);
}
if (
settings.maxExpiresSeconds > 0 &&
expiresSeconds > settings.maxExpiresSeconds
) {
throw new Error(
`Stored transfers can expire after at most ${settings.maxExpiresSeconds} seconds`,
);
}
const key = await wasm().storeGenerateKey();
const plan = planStoredUpload(files);
const created = await createStoredUpload(
key,
plan,
downloads,
expiresSeconds,
settings,
callbacks,
signal,
);
let finalized = false;
try {
await uploadStoredManifest(plan, created, settings, callbacks, signal);
await uploadStoredChunks(plan, created, settings, callbacks, signal);View on GitHub (pinned to e25f1bdc04)
Solutions
- Clamp: when settings.maxExpiresSeconds > 0, pass Math.min(requested, settings.maxExpiresSeconds)
- Drive the expiration picker maximum from the same settings value (as stored-ui.tsx does)
- Confirm settings come from the current service runtime, not a stale constant
Example fix
// before
await uploadStoredFiles({ files, settings, expiresSeconds: 7 * 24 * 3600 });
// after
const requested = 7 * 24 * 3600;
const expiresSeconds = settings.maxExpiresSeconds > 0 ? Math.min(requested, settings.maxExpiresSeconds) : requested;
await uploadStoredFiles({ files, settings, expiresSeconds }); Defensive patterns
Strategy: validation
Validate before calling
const cap = settings.maxExpiresSeconds; const expiresSeconds = cap > 0 ? Math.min(requested, cap) : requested;
Type guard
function withinExpiryLimit(expiresSeconds: number, s: StoredSettings): boolean {
return s.maxExpiresSeconds <= 0 || expiresSeconds <= s.maxExpiresSeconds;
} Try / catch
try { await uploadStoredFiles(opts); } catch (e) { if (e instanceof Error && e.message.startsWith('Stored transfers can expire after at most')) { opts.expiresSeconds = settings.maxExpiresSeconds; return uploadStoredFiles(opts); } throw e; } Prevention
- Feed settings.maxExpiresSeconds into the picker maximum (as stored-ui.tsx does)
- Remember maxExpiresSeconds === 0 means unlimited, not zero
When it happens
Trigger: Calling uploadStoredFiles with expiresSeconds: 7*24*3600 while settings.maxExpiresSeconds is 3*24*3600. Occurs when the UI offers longer expirations than the server allows or settings are stale.
Common situations: Server-side maxExpiresSeconds was reduced after the UI was built; settings fixture in tests differs from production; copied settings between environments.
Related errors
- Stored transfers can allow at most ${settings.maxDownloads}
- Stored-transfer downloads must be a positive integer
- Stored-transfer expiration must be a whole number of seconds
- Stored-transfer origin must contain only an HTTPS scheme and
- Invalid stored-transfer id
AI-assisted analysis of schollz/croc@e25f1bdc04 (2026-08-15).
Data as JSON: /api/errors/369075f4ea70c07a.
Report an issue: GitHub.