can1357/oh-my-pi · error
tmpfiles option ttl must be a duration such as 1h
Error message
tmpfiles option ttl must be a duration such as 1h
What it means
tmpfilesTtlSeconds parses the tmpfiles `ttl` option as a duration string (number plus optional unit s/m/h/d, e.g. "1h", "90s", "2d") and throws when the format does not match the expected pattern. Unlike litterbox, tmpfiles accepts arbitrary durations, so the option is free-form — but it must still be a recognizable duration.
Source
Thrown at packages/coding-agent/src/blob-broker/uploaders-anonymous.ts:152
}
function createUguuUploader(config: DestinationRuntimeConfig): BlobUploader {
return {
destination: "uguu",
async upload(request: BlobUploadRequest) {
const { url } = await uploadTextUrl("uguu", config, UGUU_UPLOAD_URL, multipartFile(request, "files[]"));
return publication("uguu", request, url, {
expiresAt: Date.now() + 3 * HOUR_MS,
remoteId: remoteName(url),
});
},
};
}
function tmpfilesTtlSeconds(config: DestinationRuntimeConfig): number {
const ttl = optionString(config, "ttl", "1h")?.trim().toLowerCase();
const match = ttl?.match(/^(\d+(?:\.\d+)?)\s*(s|m|h|d)?$/);
if (!match) throw new Error("tmpfiles option ttl must be a duration such as 1h");
const amount = Number(match[1]);
const multiplier = match[2] === "d" ? 86_400 : match[2] === "h" ? 3_600 : match[2] === "m" ? 60 : 1;
const seconds = Math.round(amount * multiplier);
if (!Number.isFinite(seconds) || seconds < 60 || seconds > 172_800) {
throw new Error("tmpfiles option ttl must be between 60 seconds and 48 hours");
}
return seconds;
}
function recordValue(value: unknown): Readonly<Record<string, unknown>> | undefined {
return typeof value === "object" && value !== null && !Array.isArray(value)
? (value as Readonly<Record<string, unknown>>)
: undefined;
}
function stringAtPath(value: unknown, path: string): string | undefined {
let current = value;
for (const segment of path.split(".").filter(Boolean)) {View on GitHub (pinned to 9690622007)
Solutions
- Use a simple duration like "45m", "2h", or "1d" — one number plus one unit (s|m|h|d), unit optional (defaults to seconds).
- Spell units as single letters: m for minutes, h for hours, d for days — not "min" or "hour".
- Split compound durations ("1h30m") into a single unit ("90m").
Example fix
// before
{ "options": { "ttl": "1 hour" } }
// after
{ "options": { "ttl": "1h" } } Defensive patterns
Strategy: validation
Validate before calling
const DURATION = /^\d+(?:\.\d+)?\s*(s|m|h|d)?$/;
const ttl = String(config.options.ttl ?? "1h");
if (!DURATION.test(ttl)) throw new Error(`tmpfiles ttl must match <number><s|m|h|d>, got: ${ttl}`); Type guard
const isSimpleDuration = (v: unknown): v is string => typeof v === "string" && /^\d+(?:\.\d+)?\s*(s|m|h|d)?$/.test(v.trim().toLowerCase());
Try / catch
try {
await uploadTmpfiles(config, req);
} catch (err) {
if (String(err).includes("tmpfiles option ttl must be a duration")) {
logger.warn("invalid ttl format; using 1h default");
config.options.ttl = "1h";
} else throw err;
} Prevention
- Use single-letter units only: s, m, h, d — never "min", "hour", "week".
- One number + one optional unit; split compound durations like 1h30m into 90m.
- Trim whitespace and lowercase the value in your own config loader.
When it happens
Trigger: Configuring tmpfiles `ttl` with text that fails /^\d+(?:\.\d+)?\s*(s|m|h|d)?$/ — e.g. "1 hour" (word unit), "h1", "1w" (unsupported week unit), "", "24", or a plain number type rather than a duration string (which would first fail optionString at uploader-runtime.ts:56).
Common situations: Writing "1 week" or "1w" in config, omitting the unit while expecting defaults, or pasting "1h30m" compound durations which the simple regex cannot parse.
Related errors
- tmpfiles option ttl must be between 60 seconds and 48 hours
- Failed to load tree-sitter language: {err}
- Destination option ${key} must be a string
- Destination option ${key} must be a finite number
- Destination option ${key} must be a boolean
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/295778e747d16ac8.
Report an issue: GitHub.