thedotmack/claude-mem · error · ServerClientError
missing_api_key
missing_api_key
Error message
${toolName}: ${resolution.reason} What it means
requireServerForObservationTool throws this ServerClientError (code 'missing_api_key') when the runtime resolves to 'server' mode but resolution.available is false — resolution.reason explains why, almost always that the required server API key (or equivalent credential/server URL) is absent. It means the runtime selection succeeded but the tool cannot authenticate to the claude-mem server.
Solutions
- Read `${toolName}: ${resolution.reason}` in the message — it names the exact missing/misconfigured item.
- Create an API key with `claude-mem server api-key create` and export it in the MCP server's environment.
- Confirm the server endpoint/URL configuration is present alongside the key.
- Restart the MCP server after setting the credentials so the context is re-resolved.
Example fix
// before CLAUDE_MEM_RUNTIME=server // after CLAUDE_MEM_RUNTIME=server CLAUDE_MEM_SERVER_API_KEY=<key from `claude-mem server api-key create`> CLAUDE_MEM_SERVER_URL=https://mem.example.com
Defensive patterns
Strategy: validation
Validate before calling
function hasServerCredentials(env: NodeJS.ProcessEnv = process.env): boolean {
return (env.CLAUDE_MEM_RUNTIME ?? '').trim() === 'server'
&& Boolean((env.CLAUDE_MEM_SERVER_API_KEY ?? '').trim());
} Try / catch
try {
ctx = requireServerForObservationTool('observation_add');
} catch (err) {
if (err instanceof ServerClientError && err.code === 'missing_api_key') {
// surface remediation: run `claude-mem server api-key create` and export the key
}
throw err;
} Prevention
- Run `claude-mem server api-key create` as part of server onboarding and store the key in a secret manager.
- Set the API key env var in the same process scope that launches the MCP server.
- Pair every CLAUDE_MEM_RUNTIME=server rollout with a credential checklist (key + server URL).
- Rotate keys on a schedule and update deployment secrets in the same change.
When it happens
Trigger: Calling a server-only observation tool while CLAUDE_MEM_RUNTIME=server is set but the server API key / credentials / endpoint configuration is missing or unusable, making resolveServerToolContext() return { available: false, reason }.
Common situations: Operator flipped CLAUDE_MEM_RUNTIME=server but never ran `claude-mem server api-key create` or didn't export the key env var; key var set in the wrong process scope; server URL misconfigured so the client can't build a valid request.
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/efe43ab24351d8ab.
Report an issue: GitHub.
Appendix: source
Thrown at src/servers/mcp-server.ts:213
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 d8bc9755e7)