thedotmack/claude-mem · warning
failed
Error message
${toolName} failed What it means
wrapHandler decorates MCP tool handlers (observation add/record/search/context/generation-status) so that any exception from execute() is caught, logged as "${toolName} failed", and converted into a structured tool error response via formatToolError rather than rejecting the RPC.
Solutions
- Read the logged underlying error for toolName to find the root cause
- Validate tool arguments against the handler's interface (ObservationAddArgs etc.)
- Confirm the backend storage/worker the tool depends on is healthy
- Rebuild/restart the MCP server if a stale build is causing internal errors
Example fix
// before
await callTool('observation_search', { limit: '10' }); // limit must be number
// after
await callTool('observation_search', { limit: 10 }); Defensive patterns
Strategy: try-catch
Validate before calling
if (typeof args.limit !== 'number') throw new TypeError('limit must be a number'); Type guard
function isObservationAddArgs(a: unknown): a is ObservationAddArgs {
return typeof a === 'object' && a !== null && 'content' in a;
} Try / catch
try {
const res = await callTool(toolName, args);
if (res.isError) console.warn(`${toolName} failed:`, res.content[0].text);
} catch (e) {
console.error('unexpected transport failure', e);
} Prevention
- Validate handler inputs before dispatch
- Keep backend storage (DB) healthy and monitored
- Pin compatible versions of client and server
When it happens
Trigger: Any of the wrapped observation tool handlers throws during execution: invalid arguments, backend storage failures, or unexpected internal errors while processing an MCP tool call.
Common situations: Malformed tool arguments from the MCP client; SQLite/database locked or corrupted; worker service unavailable; version mismatch between client expectations and server tool schema.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- recall MCP tool call failed
- Access denied: " " resolves outside the workspace ( ). MCP…
- chroma-mcp call cancelled during shutdown
- chroma-mcp connection failed
- chroma-mcp connection in backoff
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/95dc3a4d8c92edad.
Report an issue: GitHub.
Appendix: source
Thrown at src/servers/mcp-server.ts:227
`${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);
}
};
}
interface ObservationAddArgs {
projectId?: string;
serverSessionId?: string | null;
contentSessionId?: string | null;
platformSource?: string | null;
kind?: string;
content: string;
metadata?: Record<string, unknown>;
}
const handleObservationAdd = wrapHandler('observation_add', async (args: ObservationAddArgs) => {
const ctx = requireServerForObservationTool('observation_add');
if (typeof args?.content !== 'string' || args.content.trim().length === 0) {View on GitHub (pinned to d8bc9755e7)