thedotmack/claude-mem · critical · ServerClientError

missing_api_key

missing_api_key

Error message

Server API key is not configured (CLAUDE_MEM_SERVER_API_KEY).

What it means

The ServerClient's request method refuses to send anything when no API key was configured (empty, whitespace-only, or unset). Every server call (startSession, recordEvent, endSession, addObservation, searchObservations, contextObservations) funnels through request, so all of them fail with code 'missing_api_key'.

Solutions

  1. Export CLAUDE_MEM_SERVER_API_KEY with a valid server API key before starting the process.
  2. If using bootstrap, run the server-key bootstrap flow (requires CLAUDE_MEM_SERVER_DATABASE_URL) to generate and store a key.
  3. Confirm the .env file is loaded before ServerClient is constructed, not after.
  4. Check the value with trim(): a whitespace-only key is treated as missing.

Example fix

// before
const client = new ServerClient({ baseUrl, apiKey: process.env.CLAUDE_MEM_SERVER_API_KEY }); // undefined

// after
const apiKey = process.env.CLAUDE_MEM_SERVER_API_KEY;
if (!apiKey?.trim()) throw new Error('Set CLAUDE_MEM_SERVER_API_KEY before using ServerClient');
const client = new ServerClient({ baseUrl, apiKey });
Defensive patterns

Strategy: validation

Validate before calling

const apiKey = process.env.CLAUDE_MEM_SERVER_API_KEY;
if (!apiKey || !apiKey.trim()) throw new Error('CLAUDE_MEM_SERVER_API_KEY is not set');

Try / catch

try {
  await client.startSession(input);
} catch (e) {
  if (e instanceof ServerClientError && e.code === 'missing_api_key') {
    logger.warn('Server mode disabled: no API key configured');
    return null;
  } throw e;
}

Prevention

When it happens

Trigger: Constructing ServerClient without an apiKey (or with '' / whitespace) and then invoking any of its public methods, typically because CLAUDE_MEM_SERVER_API_KEY was not set in the environment when the client was created.

Common situations: Running hooks/server mode locally without the API key exported, .env not loaded at client-construction time, or pointing a client at a server deployment that requires keys while configuring none.

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/889b643fca1ca096. Report an issue: GitHub.

Appendix: source

Thrown at src/services/hooks/server-client.ts:357

      projectId: input.projectId,
      sourceType: input.sourceType,
      eventType: input.eventType,
      occurredAtEpoch: input.occurredAtEpoch,
      ...(input.serverSessionId !== undefined ? { serverSessionId: input.serverSessionId } : {}),
      ...(input.contentSessionId !== undefined ? { contentSessionId: input.contentSessionId } : {}),
      ...(input.memorySessionId !== undefined ? { memorySessionId: input.memorySessionId } : {}),
      ...(input.platformSource !== undefined ? { platformSource: normalizePlatformSourceField(input.platformSource) } : {}),
      ...(input.payload !== undefined ? { payload: input.payload } : {}),
    };
  }

  private async request<T>(
    method: 'GET' | 'POST',
    path: string,
    body?: unknown,
  ): Promise<T> {
    if (!this.apiKey || !this.apiKey.trim()) {
      throw new ServerClientError(
        'missing_api_key',
        'Server API key is not configured (CLAUDE_MEM_SERVER_API_KEY).',
      );
    }

    const url = `${this.baseUrl}${path}`;
    const init: RequestInit = {
      method,
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${this.apiKey}`,
      },
    };
    if (body !== undefined) {
      init.body = JSON.stringify(body);
    }

    let response: Response;

View on GitHub (pinned to d8bc9755e7)