can1357/oh-my-pi · error
litterbox option ttl must be one of 1h, 12h, 24h, or 72h
Error message
litterbox option ttl must be one of 1h, 12h, 24h, or 72h
What it means
litterboxTtl validates the litterbox `ttl` option against the exact set Litterbox supports (1h, 12h, 24h, 72h) and throws for anything else. Litterbox's API only accepts these four expiry values; the runtime rejects arbitrary durations up front instead of getting an opaque API error.
Source
Thrown at packages/coding-agent/src/blob-broker/uploaders-anonymous.ts:92
"catbox",
config,
CATBOX_UPLOAD_URL,
multipartFile(request, "fileToUpload", fields),
);
const id = remoteName(url);
const deleteAction =
userHash && id
? formDelete(CATBOX_UPLOAD_URL, { reqtype: "deletefiles", userhash: userHash, files: id })
: undefined;
return publication("catbox", request, url, { remoteId: id, delete: deleteAction });
},
};
}
function litterboxTtl(config: DestinationRuntimeConfig): keyof typeof LITTERBOX_TTLS {
const ttl = optionString(config, "ttl", "24h");
if (ttl && Object.hasOwn(LITTERBOX_TTLS, ttl)) return ttl as keyof typeof LITTERBOX_TTLS;
throw new Error("litterbox option ttl must be one of 1h, 12h, 24h, or 72h");
}
function createLitterboxUploader(config: DestinationRuntimeConfig): BlobUploader {
return {
destination: "litterbox",
async upload(request: BlobUploadRequest) {
const ttl = litterboxTtl(config);
const { url } = await uploadTextUrl(
"litterbox",
config,
LITTERBOX_UPLOAD_URL,
multipartFile(request, "fileToUpload", { reqtype: "fileupload", time: ttl }),
);
return publication("litterbox", request, url, {
expiresAt: Date.now() + LITTERBOX_TTLS[ttl],
remoteId: remoteName(url),
});
},View on GitHub (pinned to 9690622007)
Solutions
- Set ttl to exactly one of "1h", "12h", "24h", or "72h" (lowercase, no spaces).
- Remove the ttl option entirely to use the 24h default.
- If you need a different expiry, choose a destination that supports arbitrary durations (e.g. tmpfiles with its own bounds).
Example fix
// before
{ "destination": "litterbox", "options": { "ttl": "48h" } }
// after
{ "destination": "litterbox", "options": { "ttl": "72h" } } Defensive patterns
Strategy: validation
Validate before calling
const LITTERBOX_TTLS = ["1h", "12h", "24h", "72h"] as const;
const ttl = config.options.ttl ?? "24h";
if (!(LITTERBOX_TTLS as readonly string[]).includes(String(ttl))) throw new Error(`litterbox ttl must be one of ${LITTERBOX_TTLS.join(", ")}`); Type guard
const isLitterboxTtl = (v: unknown): v is "1h" | "12h" | "24h" | "72h" => v === "1h" || v === "12h" || v === "24h" || v === "72h";
Try / catch
try {
uploader = createLitterboxDestination(config);
} catch (err) {
if (String(err).includes("litterbox option ttl")) {
logger.warn("falling back to default litterbox ttl 24h");
config.options.ttl = "24h";
uploader = createLitterboxDestination(config);
} else throw err;
} Prevention
- Copy the exact allowed values: 1h, 12h, 24h, 72h — lowercase, no spaces.
- Encode the enum in your config schema so invalid values are caught at load time.
- Omit ttl to accept the 24h default.
When it happens
Trigger: Configuring a litterbox destination with `ttl` set to a value outside {"1h","12h","24h","72h"} — e.g. "48h", "1d", "7d", "24 hr", or a number like 24 — so Object.hasOwn(LITTERBOX_TTLS, ttl) is false.
Common situations: Users copying tmpfiles-style duration syntax ("48h", "2d") into litterbox config, assuming any duration works, or specifying the default in a different casing ("24H").
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Invalid value: ${rawValue}. Valid values: ${valid.join(", ")
- Unsupported language '{value}'. Supported: {}
- Failed to load tree-sitter language: {err}
- Destination option ${key} must be a string
- Destination option ${key} must be a finite number
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/d3b3d0d0a6643461.
Report an issue: GitHub.