thedotmack/claude-mem · error
observation_search: "query" is required
Error message
observation_search: "query" is required
What it means
Validation error inside the observation_search tool handler. After requireServerForObservationTool() passes, the handler requires args.query to be a non-empty trimmed string and throws this plain Error otherwise. It fires before ServerClient.searchObservations() is called, so no /v1/search request leaves the process.
Source
Thrown at src/servers/mcp-server.ts:306
...(args.platformSource !== undefined ? { platformSource: normalizeMcpPlatformSource(args.platformSource) } : {}),
...(args.payload !== undefined ? { payload: args.payload } : {}),
...(args.generate !== undefined ? { generate: args.generate } : {}),
};
const response = await ctx.client.recordEvent(request);
return formatJsonResult(response);
});
interface ObservationSearchArgs {
projectId?: string;
query: string;
limit?: number;
platformSource?: string | null;
}
const handleObservationSearch = wrapHandler('observation_search', async (args: ObservationSearchArgs) => {
const ctx = requireServerForObservationTool('observation_search');
if (typeof args?.query !== 'string' || args.query.trim().length === 0) {
throw new Error('observation_search: "query" is required');
}
const projectId = args.projectId && args.projectId.trim().length > 0 ? args.projectId : ctx.projectId;
const request: ServerSearchObservationsRequest = {
projectId,
query: args.query,
...(args.limit !== undefined ? { limit: args.limit } : {}),
...(args.platformSource !== undefined ? { platformSource: normalizeMcpPlatformSource(args.platformSource) } : {}),
};
const response = await ctx.client.searchObservations(request);
return formatJsonResult(response);
});
interface ObservationContextArgs {
projectId?: string;
query: string;
limit?: number;
platformSource?: string | null;
}View on GitHub (pinned to d768ba3643)
Solutions
- Pass a non-empty query string.
- If you want an unfiltered listing, use timeline or get_observations instead — observation_search requires a text query by design.
- Trim and length-check the query on the caller side before invoking.
Example fix
// before
await tools.observation_search({ limit: 20 });
// throws 'observation_search: "query" is required'
// after
await tools.observation_search({ query: 'ModeManager fallback', limit: 20 }); Defensive patterns
Strategy: validation
Validate before calling
if (typeof args?.query !== 'string' || args.query.trim().length === 0) {
return { content: [{ type: 'text', text: 'query is required for observation_search' }], isError: true };
} Type guard
function hasSearchQuery(v: unknown): v is { query: string; limit?: number } {
return typeof (v as any)?.query === 'string' && (v as any).query.trim().length > 0;
} Prevention
- Trim the query client-side and reject empty strings before calling.
- For unfiltered listings use timeline/get_observations, not observation_search.
- Document that observation_search requires a text query by design.
When it happens
Trigger: Calling observation_search with query omitted, null, non-string, or whitespace-only. The handler explicitly checks typeof args?.query === 'string' && args.query.trim().length > 0.
Common situations: Caller passes only limit/platformSource and forgets the query term; an LLM sends an empty query expecting 'list all'; query built from an empty template variable.
Related errors
- observation_add: "content" is required
- observation_record_event: "eventType" 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/a0065e8399b734fe.
Report an issue: GitHub.