can1357/oh-my-pi · error

Gemini Files API finalize response is missing ${field}

Error message

Gemini Files API finalize response is missing ${field}

What it means

requireString() throws this when a required field of the Gemini Files API finalize response's file object is absent, not a string, or an empty string. The library treats every one of file.state/file.name/file.uri/file.mimeType/file.expirationTime as mandatory to build a usable ProviderFileHandle, so a partially-populated response is rejected rather than propagated with undefined fields.

Source

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

function responseObject(value: unknown, context: string): Record<string, unknown> {
	if (typeof value !== "object" || value === null || Array.isArray(value)) {
		throw new Error(`Gemini Files API ${context} response is not a JSON object`);
	}
	return value as Record<string, unknown>;
}

async function responseJson(response: Response, context: string): Promise<Record<string, unknown>> {
	try {
		return responseObject((await response.json()) as unknown, context);
	} catch (error) {
		if (error instanceof Error && error.message.startsWith("Gemini Files API")) throw error;
		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)) {

View on GitHub (pinned to 9690622007)

Solutions

  1. Log the raw finalize response body to see which field is missing and what replaced it.
  2. Check for Google API schema/preview-version changes in the v1beta Files API release notes.
  3. Retry the upload — a finalize that lands before the file record is fully materialized can come back incomplete.
  4. Update the package if a newer version adapts to a changed response shape.

Example fix

// before: brittle full-schema assumption
catch (e) { throw new Error("upload failed: " + e.message); }
// after: inspect and adapt
const raw = await finalizeResponse.text();
console.error("finalize payload:", raw); // then fix expectations or file a bug
Defensive patterns

Strategy: type-guard

Validate before calling

null

Type guard

function isCompleteGeminiFile(f: unknown): f is { state: string; name: string; uri: string; mimeType: string; expirationTime: string } {
  if (typeof f !== "object" || f === null) return false;
  const o = f as Record<string, unknown>;
  return ["state", "name", "uri", "mimeType", "expirationTime"].every(k => typeof o[k] === "string" && o[k].length > 0);
}

Try / catch

try {
  const handle = await client.upload(request);
} catch (error) {
  if (error instanceof Error && /missing file\./.test(error.message)) {
    logger.error("Gemini finalize response incomplete", { field: error.message });
    // pin/upgrade SDK version or report schema drift
  } else throw error;
}

Prevention

When it happens

Trigger: parseFinalizedFile calls requireString(file.X, "file.X") and Google's finalize payload omits or empty-strings that field; the message interpolates the exact missing field name (e.g. 'finalize response is missing file.uri').

Common situations: Google changes or versions the v1beta Files API response schema; an unexpected state value shortens the payload; mock/stub responses in tests missing fields; a proxy stripping fields.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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