thedotmack/claude-mem · error
observation_add: "content" is required
Error message
observation_add: "content" is required
What it means
Validation error inside the observation_add tool handler. After requireServerForObservationTool() passes, the handler checks that args.content is a non-empty trimmed string and throws this plain Error if not. It is an argument-shape guard that runs before the request reaches the server client, so it never causes a network call.
Source
Thrown at src/servers/mcp-server.ts:243
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;
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) {
throw new Error('observation_add: "content" is required');
}
const projectId = args.projectId && args.projectId.trim().length > 0 ? args.projectId : ctx.projectId;
const request: ServerAddObservationRequest = {
projectId,
content: args.content,
...(args.serverSessionId !== undefined ? { serverSessionId: args.serverSessionId } : {}),
...(args.kind !== undefined ? { kind: args.kind } : {}),
...(args.metadata !== undefined ? { metadata: args.metadata } : {}),
};
const response = await ctx.client.addObservation(request);
return formatJsonResult(response);
});
interface ObservationRecordEventArgs {
projectId?: string;
serverSessionId?: string | null;
contentSessionId?: string | null;
memorySessionId?: string | null;View on GitHub (pinned to d768ba3643)
Solutions
- Provide a non-empty content string in the tool call arguments.
- If you meant to record a typed event rather than free text, use observation_record_event with eventType instead.
- Add a client-side check that trims content before calling the tool so the error never fires.
Example fix
// before
await tools.observation_add({ kind: 'note', metadata: { x: 1 } });
// throws 'observation_add: "content" is required'
// after
await tools.observation_add({
content: 'Refactored ModeManager.loadMode to fall back to code mode.',
kind: 'note',
}); Defensive patterns
Strategy: validation
Validate before calling
function validObservationContent(args: unknown): args is { content: string } {
return typeof (args as any)?.content === 'string' && (args as any).content.trim().length > 0;
}
if (!validObservationContent(args)) {
return { content: [{ type: 'text', text: 'content is required' }], isError: true };
} Type guard
function isObservationAddArgs(v: unknown): v is { content: string; kind?: string; metadata?: Record<string, unknown> } {
return typeof (v as any)?.content === 'string' && (v as any).content.trim().length > 0;
} Prevention
- Trim and length-check content on the caller side before invoking observation_add.
- Distinguish observation_add (free text) from observation_record_event (typed event) in tool docs.
- Include content in MCP tool examples so LLM clients always supply it.
When it happens
Trigger: Calling observation_add with content omitted, null, a non-string, or whitespace-only. The MCP schema may mark content as required but JSON-RPC clients can still send malformed arguments (extraProperties is allowed), so this is the last line of defense.
Common situations: LLM-driven MCP client omits content because it only passed metadata; an automation sends { kind: 'note' } with no content; content is an empty string from a templating bug; caller confused observation_add (free text) with observation_record_event (eventType).
Related errors
- observation_record_event: "eventType" is required
- observation_search: "query" is required
- observation_context: "query" is required
- observation_generation_status: "jobId" is required
- "${key}" is required
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/769e7fa0701ea08d.
Report an issue: GitHub.