can1357/oh-my-pi · error

Gemini Files API credential is required

Error message

Gemini Files API credential is required

What it means

createGeminiProviderFileClient() throws synchronously when the model IS an official Google Generative AI model but the credential argument is empty or whitespace-only. The credential becomes the x-goog-api-key header on every Files API request, and uploading without it is guaranteed to fail, so the factory fails fast instead.

Source

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

			baseUrl.search === "" &&
			baseUrl.hash === ""
		);
	} catch {
		return false;
	}
}

/**
 * Create a native Gemini Files API client for a direct Google Generative AI model.
 * Unsupported model transports return `null` without issuing a network request.
 */
export function createGeminiProviderFileClient(
	model: Model,
	credential: string,
	fetchImpl: FetchImpl = globalThis.fetch,
): ProviderFileClient | null {
	if (!isOfficialGeminiModel(model)) return null;
	if (credential.trim().length === 0) throw new Error("Gemini Files API credential is required");

	return {
		provider: "google",
		async upload(request: ProviderFileUploadRequest): Promise<ProviderFileHandle> {
			const byteLength = request.bytes.byteLength;
			let startResponse: Response;
			try {
				startResponse = await fetchImpl(GEMINI_FILES_UPLOAD_URL, {
					method: "POST",
					headers: {
						"Content-Type": "application/json",
						"X-Goog-Upload-Command": "start",
						"X-Goog-Upload-Header-Content-Length": String(byteLength),
						"X-Goog-Upload-Header-Content-Type": request.mimeType,
						"X-Goog-Upload-Protocol": "resumable",
						"x-goog-api-key": credential,
					},
					body: JSON.stringify(request.filename ? { file: { display_name: request.filename } } : { file: {} }),

View on GitHub (pinned to 9690622007)

Solutions

  1. Set GEMINI_API_KEY (or your configured credential source) to a valid Google AI Studio API key before constructing the client.
  2. Trim and check the credential at the call site: if (!key?.trim()) skip or fail before calling the factory.
  3. Verify you are passing the Google credential, not another provider's key variable.
  4. Wrap the factory call in try-catch since it throws synchronously for official Gemini models.

Example fix

// before: passing an unvalidated credential
const client = createGeminiProviderFileClient(model, process.env.GEMINI_API_KEY ?? "");
// after: validate first
const key = process.env.GEMINI_API_KEY?.trim();
if (!key) throw new Error("GEMINI_API_KEY is not set");
const client = createGeminiProviderFileClient(model, key);
Defensive patterns

Strategy: validation

Validate before calling

const key = process.env.GEMINI_API_KEY?.trim();
if (!key) throw new Error("GEMINI_API_KEY is missing or empty — cannot use Gemini Files API");

Type guard

function hasCredential(v: unknown): v is string {
  return typeof v === "string" && v.trim().length > 0;
}

Try / catch

try {
  const client = createGeminiProviderFileClient(model, key);
} catch (error) {
  if (error instanceof Error && error.message.includes("credential is required")) {
    // fall back to inline/base64 file attachment instead of Files API upload
  } else throw error;
}

Prevention

When it happens

Trigger: Calling createGeminiProviderFileClient(model, credential) with "" or " " while model.provider==="google", model.api==="google-generative-ai", and baseUrl is exactly https://generativelanguage.googleapis.com/v1beta.

Common situations: GEMINI_API_KEY / GOOGLE_API_KEY env var unset or empty; config file with a blank apikey field; credential sourced from a keychain/secret manager that returned empty; passing the wrong variable into the factory.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


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