rohitg00/ai-engineering-from-scratch · error · Error
-32603
-32603
Error message
query must be a non-empty string
What it means
The search tool executor requires arguments.query to be a non-empty string before it searches NOTES; a plain Error is thrown, which dispatch wraps as JSON-RPC -32603 Internal error. Tool argument validation failure surfaced as an internal error rather than invalid params.
Source
Thrown at phases/13-tools-and-protocols/07-building-an-mcp-server/code/main.ts:211
typeof clientInfo.name !== "string" ||
typeof clientInfo.version !== "string")
) {
throw new RpcProblem(-32602, `${CLIENT_INFO_KEY} is malformed`);
}
}
function executeList(arguments_: JsonObject): JsonObject[] {
const tag = arguments_.tag;
const items = Object.entries(NOTES)
.sort(([left], [right]) => left.localeCompare(right))
.filter(([, note]) => !tag || note.tag === tag)
.map(([id, note]) => ({ id, title: note.title, tag: note.tag }));
return [{ type: "text", text: JSON.stringify(items) }];
}
function executeSearch(arguments_: JsonObject): JsonObject[] {
if (typeof arguments_.query !== "string" || !arguments_.query) {
throw new Error("query must be a non-empty string");
}
const limit = arguments_.limit ?? 10;
if (!Number.isInteger(limit) || limit < 1 || limit > 50) {
throw new Error("limit must be an integer from 1 through 50");
}
const query = arguments_.query.toLowerCase();
const hits = Object.entries(NOTES)
.sort(([left], [right]) => left.localeCompare(right))
.filter(([, note]) => note.title.toLowerCase().includes(query) || note.body.toLowerCase().includes(query))
.map(([id, note]) => ({ id, title: note.title }))
.slice(0, limit);
return [{ type: "text", text: JSON.stringify(hits) }];
}
function executeCreate(arguments_: JsonObject): JsonObject[] {
if (typeof arguments_.title !== "string" || typeof arguments_.body !== "string") {
throw new Error("title and body must be strings");
}View on GitHub (pinned to 39ea8a1c6d)
Solutions
- Always pass a non-empty string query
- Declare query as required and minLength:1 in the tool inputSchema so callers are rejected client-side
Example fix
// before
arguments: { query: '' }
// after
arguments: { query: 'budget' } Defensive patterns
Strategy: validation
Validate before calling
if (typeof args.query !== 'string' || args.query.trim() === '') throw new ValidationError('query required'); Type guard
const isQuery = (v: unknown): v is string => typeof v === 'string' && v.length > 0;
Try / catch
// server returns isError:true content for tool errors; check result.isError before reading content
Prevention
- Make query required with minLength:1 in the tool schema
- Trim and reject whitespace-only queries client-side
When it happens
Trigger: tools/call with name:'search' and arguments where query is missing, empty, null, or a number.
Common situations: LLM tool callers passing an empty query, or argument schemas that make query optional.
Related errors
- -32600
- _meta.{PROTOCOL_VERSION_KEY} is required
- _meta.{CLIENT_CAPABILITIES_KEY} is required
- server/discover accepts no params beyond _meta
- name must be a non-empty string
AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26).
Data as JSON: /api/errors/37b7ec3076f0ea29.
Report an issue: GitHub.