thedotmack/claude-mem · error · ServerClassifiedProviderError

auth_invalid

auth_invalid

Error message

Gemini API key not configured

What it means

The Gemini provider's constructor refuses to instantiate when `options.apiKey` is falsy. It throws a ServerClassifiedProviderError with kind 'auth_invalid' because requests without a key would fail Google's auth check anyway. This fails fast at construction time instead of at first request.

Solutions

  1. Set the Gemini API key env var (e.g. GEMINI_API_KEY) in the shell, .env file, or deployment secret store
  2. Check the exact option/env name used where the provider is constructed — the value is likely undefined, not absent by design
  3. Print the value's type (not its contents) to confirm it is a non-empty string before constructing the provider
  4. Verify .env files are actually loaded in the runtime (dotenv config called before provider construction)

Example fix

// before
const provider = new GeminiObservationProvider({ apiKey: process.env.GEMINI_KEY });

// after
const apiKey = process.env.GEMINI_API_KEY;
if (!apiKey) throw new Error('GEMINI_API_KEY is not set');
const provider = new GeminiObservationProvider({ apiKey });
Defensive patterns

Strategy: validation

Validate before calling

const apiKey = process.env.GEMINI_API_KEY;
if (typeof apiKey !== 'string' || apiKey.length === 0) {
  throw new Error('GEMINI_API_KEY must be a non-empty string');
}
const provider = new GeminiObservationProvider({ apiKey });

Type guard

function hasApiKey(o: GeminiObservationProviderOptions): o is GeminiObservationProviderOptions & { apiKey: string } {
  return typeof o.apiKey === 'string' && o.apiKey.length > 0;
}

Try / catch

try {
  provider = new GeminiObservationProvider({ apiKey });
} catch (e) {
  if (e instanceof ServerClassifiedProviderError && e.kind === 'auth_invalid') {
    throw new ConfigError('Gemini provider misconfigured: apiKey missing. Set GEMINI_API_KEY.');
  }
  throw e;
}

Prevention

When it happens

Trigger: Constructing `new GeminiObservationProvider({...})` with an options object whose `apiKey` property is undefined, null, or an empty string.

Common situations: Missing GEMINI_API_KEY / GOOGLE_API_KEY environment variable; reading the env var with the wrong name; a config loader returning undefined for an unset key; passing a variable that was never populated due to a typo in the key lookup.

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 thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/26c9d40a80055c7d. Report an issue: GitHub.

Appendix: source

Thrown at src/server/generation/providers/GeminiObservationProvider.ts:137

    });
  }

  return classifyHttpProviderError({
    ...input,
    providerLabel: 'Gemini',
  });
}

export class GeminiObservationProvider implements ServerGenerationProvider {
  readonly providerLabel = 'gemini' as const;
  private readonly apiKey: string;
  private readonly model: string;
  private readonly maxOutputTokens: number;
  private readonly fetchImpl: typeof fetch;

  constructor(options: GeminiObservationProviderOptions) {
    if (!options.apiKey) {
      throw new ServerClassifiedProviderError('Gemini API key not configured', {
        kind: 'auth_invalid',
        cause: new Error('apiKey is required'),
      });
    }
    this.apiKey = options.apiKey;
    this.model = options.model ?? DEFAULT_MODEL;
    this.maxOutputTokens = options.maxOutputTokens ?? 4096;
    this.fetchImpl = options.fetchImpl ?? fetch;
  }

  async generate(
    context: ServerGenerationContext,
    signal?: AbortSignal,
  ): Promise<ServerGenerationResult> {
    const { prompt, skippedAll } = buildServerGenerationPrompt(context);
    if (skippedAll) {
      return {
        rawText: '<skip_summary reason="all_events_private" />',

View on GitHub (pinned to d8bc9755e7)