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.name

What it means

parseFinalizedFile() throws this when file.name passes requireString but fails the format check /^files\/[^/]+$/. The name is used both as the handle id and to build the DELETE URL (https://generativelanguage.googleapis.com/v1beta/files/{name}), so a malformed name would produce broken resource URLs downstream.

Source

Thrown at packages/coding-agent/src/blob-broker/provider-files-gemini.ts:46

		throw new Error(`Gemini Files API ${context} response is not valid JSON`);
	}
}

function requireString(value: unknown, field: string): string {
	if (typeof value !== "string" || value.length === 0) {
		throw new Error(`Gemini Files API finalize response is missing ${field}`);
	}
	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" &&

View on GitHub (pinned to 9690622007)

Solutions

  1. Log the actual file.name value returned to see how it differs from files/{id}.
  2. Check the pinned API version (v1beta) against Google's current Files API docs for name-format changes.
  3. Update to a package version that matches the current API response format.
  4. If behind a proxy, verify it is not rewriting the JSON response body.

Example fix

// before: assuming the name format
const handle = await client.upload(req);
// after: capture raw payload for diagnosis
const raw = await finalizeResponse.text();
console.error("file.name was:", JSON.parse(raw)?.file?.name); // compare with /^files\/[^/]+$/
Defensive patterns

Strategy: type-guard

Validate before calling

null

Type guard

function isValidGeminiFileName(name: unknown): name is string {
  return typeof name === "string" && /^files\/[^/]+$/.test(name);
}

Try / catch

try {
  const handle = await client.upload(request);
} catch (error) {
  if (error instanceof Error && error.message.includes("invalid file.name")) {
    logger.error("Gemini file.name format drifted", { message: error.message });
    // report/upgrade; do not use the malformed name for DELETE URLs
  } else throw error;
}

Prevention

When it happens

Trigger: Google's finalize payload returns a file.name that is empty after non-empty check, contains slashes beyond the files/ prefix, or uses a completely different id scheme (API version change).

Common situations: Google changing the Files API resource-name format in a new API version or preview; proxies/rewriters altering the response; hand-rolled mocks returning wrong-shaped names in tests.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/afb35202a0210777. Report an issue: GitHub.