{"record":{"id":"26c9d40a80055c7d","repo":"thedotmack/claude-mem","slug":"auth-invalid-26c9d4","errorCode":"auth_invalid","errorMessage":"Gemini API key not configured","messagePattern":"Gemini API key not configured","errorType":"exception","errorClass":"ServerClassifiedProviderError","httpStatus":null,"severity":"error","filePath":"src/server/generation/providers/GeminiObservationProvider.ts","lineNumber":137,"sourceCode":"    });\n  }\n\n  return classifyHttpProviderError({\n    ...input,\n    providerLabel: 'Gemini',\n  });\n}\n\nexport class GeminiObservationProvider implements ServerGenerationProvider {\n  readonly providerLabel = 'gemini' as const;\n  private readonly apiKey: string;\n  private readonly model: string;\n  private readonly maxOutputTokens: number;\n  private readonly fetchImpl: typeof fetch;\n\n  constructor(options: GeminiObservationProviderOptions) {\n    if (!options.apiKey) {\n      throw new ServerClassifiedProviderError('Gemini API key not configured', {\n        kind: 'auth_invalid',\n        cause: new Error('apiKey is required'),\n      });\n    }\n    this.apiKey = options.apiKey;\n    this.model = options.model ?? DEFAULT_MODEL;\n    this.maxOutputTokens = options.maxOutputTokens ?? 4096;\n    this.fetchImpl = options.fetchImpl ?? fetch;\n  }\n\n  async generate(\n    context: ServerGenerationContext,\n    signal?: AbortSignal,\n  ): Promise<ServerGenerationResult> {\n    const { prompt, skippedAll } = buildServerGenerationPrompt(context);\n    if (skippedAll) {\n      return {\n        rawText: '<skip_summary reason=\"all_events_private\" />',","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/server/generation/providers/GeminiObservationProvider.ts#L119-L155","documentation":"Thrown by the GeminiObservationProvider constructor when options.apiKey is falsy. It is a ServerClassifiedProviderError with kind 'auth_invalid', meaning the Gemini generation provider cannot authenticate. Auth is validated at construction time so the failure is surfaced before any request is attempted.","triggerScenarios":"Instantiating GeminiObservationProvider with an empty/undefined apiKey; the configured provider is 'gemini' but GEMINI_API_KEY (or the equivalent setting) is unset; the settings layer resolved the key to an empty string.","commonSituations":"Operator selects the gemini provider but never exports the Gemini key. A .env file isn't loaded. The key was revoked in Google AI Studio. Local-dev bypass hides the gap until provider construction.","solutions":["Set GEMINI_API_KEY (or the configured setting) to a valid key from Google AI Studio before launch.","Switch to a different provider if Gemini was selected by mistake, supplying that provider's key.","Confirm the settings/env layer resolves the key (check length, never the value).","Re-run after fixing config."],"exampleFix":"// before: no key supplied\nnew GeminiObservationProvider({ /* apiKey omitted */ });\n// after\nnew GeminiObservationProvider({ apiKey: process.env.GEMINI_API_KEY });\n// plus: export GEMINI_API_KEY=AIza... before launch","handlingStrategy":"validation","validationCode":"function resolveGeminiKey(): string {\n  const key = process.env.GEMINI_API_KEY ?? readSetting('geminiApiKey');\n  if (!key || !key.trim()) {\n    throw new Error('GEMINI_API_KEY is not set; cannot use the gemini provider');\n  }\n  return key.trim();\n}","typeGuard":"function hasApiKey(opts: unknown): opts is { apiKey: string } {\n  return typeof (opts as { apiKey?: unknown })?.apiKey === 'string'\n    && (opts as { apiKey: string }).apiKey.trim().length > 0;\n}","tryCatchPattern":"try {\n  provider = new GeminiObservationProvider({ apiKey });\n} catch (error) {\n  if (error instanceof ServerClassifiedProviderError && error.kind === 'auth_invalid') {\n    // pick a different configured provider or exit with guidance\n  } else throw error;\n}","preventionTips":["Validate required keys at startup and fail fast with a clear, provider-specific message.","Load .env via the same loader in all environments.","Keep keys in a secret manager and probe for revocation."],"tags":["auth","gemini","provider","config","api-key"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}