{"record":{"id":"68c7930e49b855fb","repo":"thedotmack/claude-mem","slug":"transport","errorCode":"transport","errorMessage":"${toolName} requires CLAUDE_MEM_RUNTIME=server. Current runtime is \"worker\"; use the existing search/timeline/get_observations tools for worker-mode memory access.","messagePattern":"(.+?) requires CLAUDE_MEM_RUNTIME=server\\. Current runtime is \"worker\"; use the existing search/timeline/get_observations tools for worker-mode memory access\\.","errorType":"error_code","errorClass":"ServerClientError","httpStatus":null,"severity":"error","filePath":"src/servers/mcp-server.ts","lineNumber":206,"sourceCode":"      text: `Tool error: ${error instanceof Error ? error.message : String(error)}`,\n    }],\n    isError: true as const,\n  };\n}\n\nfunction formatJsonResult(payload: unknown): { content: Array<{ type: 'text'; text: string }> } {\n  return {\n    content: [{\n      type: 'text' as const,\n      text: JSON.stringify(payload, null, 2),\n    }],\n  };\n}\n\nfunction requireServerForObservationTool(toolName: string): ServerAvailable {\n  const resolution = resolveServerToolContext();\n  if (!resolution) {\n    throw new ServerClientError(\n      'transport',\n      `${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) {","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/servers/mcp-server.ts#L188-L224","documentation":"Thrown by requireServerForObservationTool() when selectRuntime() returns a runtime other than 'server' (i.e. the install is in 'worker' runtime). The observation_* server-backed tools (observation_add, observation_record_event, observation_search, observation_context, observation_generation_status) only exist on the server /v1 surface, so they refuse to run against the worker. The error tells the caller which worker-mode equivalents to use instead.","triggerScenarios":"Calling any observation_* tool while CLAUDE_MEM_RUNTIME=worker (or unset and resolving to worker). selectRuntime() returns 'worker', resolveServerToolContext() returns null, and the guard throws a ServerClientError of kind 'transport'.","commonSituations":"User upgraded to a version that introduced server-mode tools but never switched CLAUDE_MEM_RUNTIME to 'server' in settings/env; an MCP client auto-discovers advertised tools and calls one in a worker-only install; settings file has a typo in the runtime value so it falls back to worker.","solutions":["Set the runtime to server: put CLAUDE_MEM_RUNTIME=server in your settings/env, then restart the MCP server (runtime is re-resolved per call, so no rebuild needed).","If you cannot run the server runtime, stop calling the observation_* tools and use the worker-mode equivalents the message names: search, timeline, get_observations.","Verify the switch took effect by checking selectRuntime()'s return or the debug log line from resolveServerToolContext()."],"exampleFix":"// before\n// settings: { \"runtime\": \"worker\" }\n// → observation_add throws 'requires CLAUDE_MEM_RUNTIME=server'\n\n// after\n// settings.json\n{ \"runtime\": \"server\", \"serverBaseUrl\": \"https://...\", \"apiKey\": \"cmem_...\" }\n// or env\nexport CLAUDE_MEM_RUNTIME=server","handlingStrategy":"validation","validationCode":"// Resolve runtime before calling observation_* tools.\nimport { selectRuntime } from '<runtime-module>';\nif (selectRuntime() !== 'server') {\n  // do not call observation_*; use search/timeline/get_observations instead\n}","typeGuard":"function isServerRuntime(): boolean {\n  // mirrors resolveServerToolContext()'s null branch\n  try { return selectRuntime() === 'server'; } catch { return false; }\n}","tryCatchPattern":"try {\n  await tools.observation_add({ content });\n} catch (e) {\n  if (e instanceof ServerClientError && e.kind === 'transport' && /requires CLAUDE_MEM_RUNTIME=server/.test(e.message)) {\n    // wrong runtime — fall back to worker-mode tools\n    await tools.search({ query: content });\n  } else throw e;\n}","preventionTips":["Only advertise observation_* tools when selectRuntime() === 'server' (filter the tools list by runtime).","Document in each tool description that it is server-only so LLM clients avoid calling it in worker mode.","Re-resolve runtime per call (already cheap) so flipping CLAUDE_MEM_RUNTIME takes effect without restart."],"tags":["mcp","runtime","config","server-mode"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}