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

  1. Read the logged underlying error for toolName to find the root cause
  2. Validate tool arguments against the handler's interface (ObservationAddArgs etc.)
  3. Confirm the backend storage/worker the tool depends on is healthy
  4. 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

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


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)