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
- Run the server bootstrap/credential provisioning step so serverBaseUrl, apiKey, and projectId are all written into settings.
- Open the settings file (or CLAUDE_MEM_SERVER_* env) and confirm all three of url, apiKey, projectId are present and non-empty.
- Confirm the API key is still valid by calling the server /v1 health or a cheap endpoint; re-bootstrap if revoked.
- 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
- Run the bootstrap step as part of install so url/apiKey/projectId are written together.
- Validate the settings triple on startup and fail fast with a clear message rather than at first tool call.
- Re-verify the API key periodically (cheap health call) since keys can be revoked server-side.
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
- transport
- Unknown Claude model: ${options.model}. Allowed: ${[...allow
- auth_invalid
- auth_invalid
- auth_invalid
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/efe43ab24351d8ab.
Report an issue: GitHub.