thedotmack/claude-mem · error · ServerClientError

missing_api_key

missing_api_key

Error message

${toolName}: ${resolution.reason}

What it means

Thrown by requireServerForObservationTool() when the server runtime IS selected (selectRuntime() === 'server') but buildServerContext() returns null, meaning required configuration is incomplete. The ServerClientError kind is 'missing_api_key' and the reason text is the one built in resolveServerToolContext(): 'server runtime is selected but configuration is incomplete (missing url, api key, or project id)'.

Source

Thrown at src/servers/mcp-server.ts:212

function formatJsonResult(payload: unknown): { content: Array<{ type: 'text'; text: string }> } {
  return {
    content: [{
      type: 'text' as const,
      text: JSON.stringify(payload, null, 2),
    }],
  };
}

function requireServerForObservationTool(toolName: string): ServerAvailable {
  const resolution = resolveServerToolContext();
  if (!resolution) {
    throw new ServerClientError(
      'transport',
      `${toolName} requires CLAUDE_MEM_RUNTIME=server. Current runtime is "worker"; use the existing search/timeline/get_observations tools for worker-mode memory access.`,
    );
  }
  if (!resolution.available) {
    throw new ServerClientError('missing_api_key', `${toolName}: ${resolution.reason}`);
  }
  return resolution;
}

function wrapHandler<Args>(
  toolName: string,
  execute: (args: Args) => Promise<{ content: Array<{ type: 'text'; text: string }> }>,
): (args: Args) => Promise<{ content: Array<{ type: 'text'; text: string }>; isError?: boolean }> {
  return async (args: Args) => {
    try {
      return await execute(args);
    } catch (error) {
      const err = error instanceof Error ? error : new Error(String(error));
      logger.warn('SYSTEM', `${toolName} failed`, undefined, err);
      return formatToolError(error);
    }
  };
}

View on GitHub (pinned to d768ba3643)

Solutions

  1. Run the server bootstrap/credential provisioning step so serverBaseUrl, apiKey, and projectId are all written into settings.
  2. Open the settings file (or CLAUDE_MEM_SERVER_* env) and confirm all three of url, apiKey, projectId are present and non-empty.
  3. Confirm the API key is still valid by calling the server /v1 health or a cheap endpoint; re-bootstrap if revoked.
  4. If you intentionally have no server, set CLAUDE_MEM_RUNTIME=worker to stop advertising the server-only tools.

Example fix

// before — runtime=server but no apiKey in settings
{ "runtime": "server", "serverBaseUrl": "https://api.example.com" }
// → ServerClientError(missing_api_key, '...missing url, api key, or project id')

// after
{
  "runtime": "server",
  "serverBaseUrl": "https://api.example.com",
  "apiKey": "cmem_<from-bootstrap>",
  "projectId": "<from-bootstrap>"
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate all three required server-config fields before calling observation_* tools.
const { serverBaseUrl, apiKey, projectId } = readSettings();
const ok = Boolean(serverBaseUrl && apiKey && projectId);
if (!ok) {
  throw new Error('Server runtime selected but url/apiKey/projectId missing — run bootstrap');
}

Type guard

function serverContextComplete(ctx: { serverBaseUrl?: string; apiKey?: string; projectId?: string } | null): ctx is { serverBaseUrl: string; apiKey: string; projectId: string } {
  return !!ctx && !!ctx.serverBaseUrl && !!ctx.apiKey && !!ctx.projectId;
}

Try / catch

try {
  await tools.observation_add({ content });
} catch (e) {
  if (e instanceof ServerClientError && e.kind === 'missing_api_key') {
    // prompt the user to run bootstrap / fix settings
    notifyUser('Server config incomplete: ' + e.message);
  } else throw e;
}

Prevention

When it happens

Trigger: CLAUDE_MEM_RUNTIME=server is set, but at least one of serverBaseUrl, apiKey, or projectId is missing/empty, so buildServerContext() yields null and resolution.available is false. Any observation_* tool call then hits this guard.

Common situations: User set runtime=server but forgot the API key; serverBaseUrl points at the wrong host; the project id was never bootstrapped; key was revoked/expired and the bootstrap step that writes it did not run; settings file partially overwritten.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12). Data as JSON: /api/errors/efe43ab24351d8ab. Report an issue: GitHub.