{"record":{"id":"95dc3a4d8c92edad","repo":"thedotmack/claude-mem","slug":"toolname-failed","errorCode":null,"errorMessage":"${toolName} failed","messagePattern":"(.+?) failed","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/servers/mcp-server.ts","lineNumber":227,"sourceCode":"      `${toolName} requires CLAUDE_MEM_RUNTIME=server. Current runtime is \"worker\"; use the existing search/timeline/get_observations tools for worker-mode memory access.`,\n    );\n  }\n  if (!resolution.available) {\n    throw new ServerClientError('missing_api_key', `${toolName}: ${resolution.reason}`);\n  }\n  return resolution;\n}\n\nfunction wrapHandler<Args>(\n  toolName: string,\n  execute: (args: Args) => Promise<{ content: Array<{ type: 'text'; text: string }> }>,\n): (args: Args) => Promise<{ content: Array<{ type: 'text'; text: string }>; isError?: boolean }> {\n  return async (args: Args) => {\n    try {\n      return await execute(args);\n    } catch (error) {\n      const err = error instanceof Error ? error : new Error(String(error));\n      logger.warn('SYSTEM', `${toolName} failed`, undefined, err);\n      return formatToolError(error);\n    }\n  };\n}\n\ninterface ObservationAddArgs {\n  projectId?: string;\n  serverSessionId?: string | null;\n  contentSessionId?: string | null;\n  platformSource?: string | null;\n  kind?: string;\n  content: string;\n  metadata?: Record<string, unknown>;\n}\n\nconst handleObservationAdd = wrapHandler('observation_add', async (args: ObservationAddArgs) => {\n  const ctx = requireServerForObservationTool('observation_add');\n  if (typeof args?.content !== 'string' || args.content.trim().length === 0) {","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/servers/mcp-server.ts#L209-L245","documentation":"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.","triggerScenarios":"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.","commonSituations":"Malformed tool arguments from the MCP client; SQLite/database locked or corrupted; worker service unavailable; version mismatch between client expectations and server tool schema.","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"],"exampleFix":"// before\nawait callTool('observation_search', { limit: '10' }); // limit must be number\n// after\nawait callTool('observation_search', { limit: 10 });","handlingStrategy":"try-catch","validationCode":"if (typeof args.limit !== 'number') throw new TypeError('limit must be a number');","typeGuard":"function isObservationAddArgs(a: unknown): a is ObservationAddArgs {\n  return typeof a === 'object' && a !== null && 'content' in a;\n}","tryCatchPattern":"try {\n  const res = await callTool(toolName, args);\n  if (res.isError) console.warn(`${toolName} failed:`, res.content[0].text);\n} catch (e) {\n  console.error('unexpected transport failure', e);\n}","preventionTips":["Validate handler inputs before dispatch","Keep backend storage (DB) healthy and monitored","Pin compatible versions of client and server"],"tags":["mcp","tool-handler","rpc"],"backgroundTag":"api-request-failed","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}