{"record":{"id":"614776af069c4136","repo":"danny-avila/LibreChat","slug":"gemini-image-generation-requires-one-of-user-prov","errorCode":null,"errorMessage":"Gemini Image Generation requires one of: user-provided API key, GEMINI_API_KEY or GOOGLE_KEY env var, or a valid Google service account. Service account file not found or invalid at: ${credentialsPath}","messagePattern":"Gemini Image Generation requires one of: user-provided API key, GEMINI_API_KEY or GOOGLE_KEY env var, or a valid Google service account\\. Service account file not found or invalid at: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"api/app/clients/tools/structured/GeminiImageGen.js","lineNumber":113,"sourceCode":"async function initializeGeminiClient(options = {}) {\n  const geminiKey = options.GEMINI_API_KEY;\n  if (geminiKey) {\n    logger.debug('[GeminiImageGen] Using Gemini API with GEMINI_API_KEY');\n    return new GoogleGenAI({ apiKey: geminiKey });\n  }\n\n  const googleKey = options.GOOGLE_KEY;\n  if (googleKey) {\n    logger.debug('[GeminiImageGen] Using Gemini API with GOOGLE_KEY');\n    return new GoogleGenAI({ apiKey: googleKey });\n  }\n\n  logger.debug('[GeminiImageGen] Using Vertex AI with service account');\n  const credentialsPath = getDefaultServiceKeyPath();\n  const serviceKey = await loadServiceKey(credentialsPath);\n\n  if (!serviceKey || !serviceKey.project_id) {\n    throw new Error(\n      'Gemini Image Generation requires one of: user-provided API key, GEMINI_API_KEY or GOOGLE_KEY env var, or a valid Google service account. ' +\n        `Service account file not found or invalid at: ${credentialsPath}`,\n    );\n  }\n\n  return new GoogleGenAI({\n    vertexai: true,\n    project: serviceKey.project_id,\n    location: process.env.GOOGLE_CLOUD_LOCATION || process.env.GOOGLE_LOC || 'global',\n    googleAuthOptions: { credentials: serviceKey },\n  });\n}\n\n/**\n * Convert image files to Gemini inline data format\n * @param {Object} params - Parameters\n * @returns {Promise<Array>} - Array of inline data objects\n */","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/api/app/clients/tools/structured/GeminiImageGen.js#L95-L131","documentation":"Thrown by initializeGeminiClient when no API key path is available and the Vertex AI service-account fallback also fails. The function tries, in order: options.GEMINI_API_KEY, options.GOOGLE_KEY (both resolved upstream by loadAuthValues), then a service-account JSON at GOOGLE_SERVICE_KEY_FILE or api/data/auth.json. The throw fires only if the loaded file is missing, unreadable, or lacks a project_id field.","triggerScenarios":"Creating the Gemini image tool (which calls initializeGeminiClient on first image request) when (a) neither GEMINI_API_KEY nor GOOGLE_KEY was resolved into the fields, AND (b) loadServiceKey(credentialsPath) returned null/undefined OR the parsed JSON has no project_id.","commonSituations":"First-run setup that never placed a Google service-account JSON at api/data/auth.json; GOOGLE_SERVICE_KEY_FILE points to a stale or deleted path; the JSON is a non-service-account key (e.g., an OAuth client secret) that has no project_id; the file exists but is empty/corrupt; running in a container without the mounted secret volume.","solutions":["Set `GEMINI_API_KEY` (or `GOOGLE_KEY`) in .env for the simplest path — the API-key branch returns before touching any file.","If using Vertex AI, put a valid service-account JSON at api/data/auth.json or set GOOGLE_SERVICE_KEY_FILE to its absolute path, and confirm the JSON contains a `project_id` field.","Validate the file with `node -e \"const k=require('./api/data/auth.json'); console.log(k.project_id)\"` to ensure project_id resolves.","If loadAuthValues is supposed to inject the key, check that the user/endpoint credential flow actually populated GEMINI_API_KEY before the tool runs."],"exampleFix":"// before — no key env, missing/invalid service account\nconst t = createGeminiImageTool({ /* no GEMINI_API_KEY/GOOGLE_KEY */ });\nawait t.invoke({ prompt: 'a fox' }); // throws\n\n// after — simplest fix: API key via env\n// .env: GEMINI_API_KEY=AIza...\n\n// or — Vertex AI: valid service account\n// api/data/auth.json must contain { \"project_id\": \"my-gcp-project\", ... }","handlingStrategy":"validation","validationCode":"async function ensureGeminiCreds(fields = {}) {\n  const hasKey = Boolean(fields.GEMINI_API_KEY || fields.GOOGLE_KEY);\n  if (hasKey) return;\n  const fs = require('fs');\n  const path = require('path');\n  const credPath = process.env.GOOGLE_SERVICE_KEY_FILE || path.join(process.cwd(), 'api', 'data', 'auth.json');\n  if (!fs.existsSync(credPath)) {\n    throw new Error('No Gemini API key and no service account at ' + credPath);\n  }\n  const key = JSON.parse(fs.readFileSync(credPath, 'utf8'));\n  if (!key.project_id) throw new Error('Service account JSON missing project_id at ' + credPath);\n}","typeGuard":"function hasGeminiCreds(fields) {\n  return Boolean(fields?.GEMINI_API_KEY || fields?.GOOGLE_KEY);\n}","tryCatchPattern":"try {\n  await geminiTool.invoke({ prompt });\n} catch (e) {\n  if (/Gemini Image Generation requires/.test(e.message)) {\n    return 'Gemini image generation is not configured (API key or service account required).';\n  }\n  throw e;\n}","preventionTips":["Prefer GEMINI_API_KEY for the simplest setup; only use a service account when Vertex AI is required.","Validate the service-account JSON contains project_id at deploy time.","Mount the secret file via your orchestrator rather than committing it."],"tags":["gemini","google","vertex-ai","config","service-account","api-key"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}