thedotmack/claude-mem · error
observation_search: "query" is required
Error message
observation_search: "query" is required
What it means
The observation_search tool handler requires a 'query' argument and throws this error when it is missing, not a string, or blank after trimming. Search without a query is meaningless, so the handler fails fast before building the ServerSearchObservationsRequest.
Solutions
- Supply a non-empty query string, e.g. { query: 'deployment errors' }
- If you want unfiltered listing, use a broad query term or a different listing tool instead of an empty query
- Guard the caller: if (!query?.trim()) skip the call or prompt the user for input
- Verify the MCP client is not URL-encoding/trimming the query down to nothing
Example fix
// before
await callTool('observation_search', { limit: 10 });
// after
await callTool('observation_search', { query: 'typescript build failure', limit: 10 }); Defensive patterns
Strategy: validation
Validate before calling
function canSearch(args) {
return typeof args?.query === 'string' && args.query.trim().length > 0;
}
if (!canSearch(args)) return []; // skip the call instead of erroring Type guard
function hasQuery(args: unknown): args is { query: string } & Record<string, unknown> {
return typeof (args as any)?.query === 'string' && (args as any).query.trim().length > 0;
} Try / catch
try {
return await callTool('observation_search', { query, limit });
} catch (e) {
if (e instanceof Error && e.message.includes('"query" is required')) {
return { results: [], skipped: 'empty query' };
}
throw e;
} Prevention
- Disable search UIs/agents when the query box is empty
- Trim and check user input before forwarding it as query
- Use a dedicated listing tool for unfiltered browsing rather than an empty query
- Validate required fields against the tool schema in your MCP client wrapper
When it happens
Trigger: Invoking observation_search with args where query is undefined, null, a non-string, or '' / whitespace-only (handler check: typeof args?.query !== 'string' || args.query.trim().length === 0).
Common situations: Clients sending only limit or projectId; a UI passing an empty search box value straight through; refactors renaming query to q or searchTerm; agents constructing empty search calls to 'list all' observations.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- " " is required
- Missing required argument: name
- observation_context: "query" is required
- observation_generation_status: "jobId" is required
- observation_record_event: "eventType" is required
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/a0065e8399b734fe.
Report an issue: GitHub.
Appendix: source
Thrown at src/servers/mcp-server.ts:311
...(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 d8bc9755e7)