can1357/oh-my-pi · error
Gemini Files API finalize response contains an invalid file.
Error message
Gemini Files API finalize response contains an invalid file.expirationTime
What it means
parseFinalizedFile() throws this when file.expirationTime is a non-empty string but Date.parse() returns NaN, i.e. it is not a parseable RFC 3339 timestamp. The library converts it to a numeric expiresAt epoch for the handle, so an unparseable timestamp cannot be represented.
Source
Thrown at packages/coding-agent/src/blob-broker/provider-files-gemini.ts:53
}
return value;
}
function parseFinalizedFile(payload: Record<string, unknown>): GeminiFileResource {
const file = responseObject(payload.file, "finalize file");
const state = requireString(file.state, "file.state");
if (state !== "ACTIVE") throw new Error("Gemini Files API finalized file state is not ACTIVE");
const name = requireString(file.name, "file.name");
if (!/^files\/[^/]+$/.test(name)) {
throw new Error("Gemini Files API finalize response contains an invalid file.name");
}
const uri = requireString(file.uri, "file.uri");
const mimeType = requireString(file.mimeType, "file.mimeType");
const expirationTime = requireString(file.expirationTime, "file.expirationTime");
const expiresAt = Date.parse(expirationTime);
if (!Number.isFinite(expiresAt)) {
throw new Error("Gemini Files API finalize response contains an invalid file.expirationTime");
}
return { name, uri, mimeType, expiresAt };
}
function isOfficialGeminiModel(model: Model): boolean {
if (model.provider !== "google" || model.api !== "google-generative-ai") return false;
try {
const baseUrl = new URL(model.baseUrl);
return (
baseUrl.protocol === "https:" &&
baseUrl.hostname === "generativelanguage.googleapis.com" &&
baseUrl.port === "" &&
baseUrl.username === "" &&
baseUrl.password === "" &&
baseUrl.pathname.replace(/\/+$/, "") === "/v1beta" &&
baseUrl.search === "" &&
baseUrl.hash === ""
);View on GitHub (pinned to 9690622007)
Solutions
- Log the raw file.expirationTime string to see its actual format.
- Check whether the API version you hit renamed the field (expireTime vs expirationTime) and update the package.
- Convert epoch-seconds values yourself if Google switched formats, or upgrade to a version that handles it.
- File/report a compat issue if a Google schema change is confirmed.
Example fix
// before: trusting the timestamp format Date.parse(file.expirationTime); // after: normalize before parsing const raw = file.expirationTime; const expiresAt = /^\d+$/.test(raw) ? Number(raw) * 1000 : Date.parse(raw);
Defensive patterns
Strategy: validation
Validate before calling
null
Type guard
function isParseableTimestamp(v: unknown): v is string {
return typeof v === "string" && Number.isFinite(Date.parse(v));
} Try / catch
try {
const handle = await client.upload(request);
} catch (error) {
if (error instanceof Error && error.message.includes("invalid file.expirationTime")) {
// log raw payload, then treat expiry as unknown: refresh via GET /v1beta/{name}
} else throw error;
} Prevention
- Check raw expirationTime values when upgrading API versions (field renames are common)
- Keep fixtures in tests using RFC 3339 timestamps exactly as Google returns them
- Track Google's field naming (expirationTime vs expireTime) across API revisions
- Pin the package version alongside the API version you validated against
When it happens
Trigger: Google's finalize response supplies file.expirationTime in an unexpected format (locale date, epoch seconds instead of ISO string, or a renamed field leaving a stale value).
Common situations: API version drift changing the timestamp format; field renamed to e.g. expireTime in newer API revisions so the parsed value is undefined/empty; response tampering by middleware.
Related errors
- Gemini Files API finalize response contains an invalid file.
- ${context} omitted ${field}
- Codex Security cloud returned an invalid object
- Codex Security cloud response is missing ${field}
- Unsupported language '{value}'. Supported: {}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/8571751fd7154957.
Report an issue: GitHub.