{"record":{"id":"e44e6ccf99f4ae4a","repo":"rohitg00/ai-engineering-from-scratch","slug":"32602","errorCode":"-32602","errorMessage":"params must be an object","messagePattern":"params must be an object","errorType":"error_code","errorClass":"RpcProblem","httpStatus":null,"severity":"error","filePath":"phases/13-tools-and-protocols/07-building-an-mcp-server/code/main.ts","lineNumber":168,"sourceCode":"  return {\n    resultType: \"complete\",\n    ...payload,\n    ...(cache ?? {}),\n    _meta: { [SERVER_INFO_KEY]: { ...SERVER_INFO } },\n  };\n}\n\nfunction validateRequest(message: JsonRpcRequest): void {\n  if (message.jsonrpc !== \"2.0\" || typeof message.method !== \"string\") {\n    throw new RpcProblem(-32600, \"Invalid Request\");\n  }\n  const requestId: unknown = message.id;\n  if (requestId !== undefined && !isValidRequestId(requestId)) {\n    throw new RpcProblem(-32600, \"id must be a string or integer\");\n  }\n  const params = message.params;\n  if (!params || typeof params !== \"object\" || Array.isArray(params)) {\n    throw new RpcProblem(-32602, \"params must be an object\");\n  }\n  const meta = params._meta;\n  if (!meta || typeof meta !== \"object\" || Array.isArray(meta)) {\n    throw new RpcProblem(-32602, \"params._meta is required\");\n  }\n  const requested = meta[VERSION_KEY];\n  if (typeof requested !== \"string\") {\n    throw new RpcProblem(-32602, `${VERSION_KEY} is required`);\n  }\n  if (!SUPPORTED_VERSIONS.includes(requested)) {\n    throw new RpcProblem(-32022, \"Unsupported protocol version\", {\n      requested,\n      supported: [...SUPPORTED_VERSIONS],\n    });\n  }\n  const capabilities = meta[CAPABILITIES_KEY];\n  if (!capabilities || typeof capabilities !== \"object\" || Array.isArray(capabilities)) {\n    throw new RpcProblem(-32602, `${CAPABILITIES_KEY} is required`);","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/rohitg00/ai-engineering-from-scratch/blob/39ea8a1c6d0b61f071226eff7ede4d4105fed820/phases/13-tools-and-protocols/07-building-an-mcp-server/code/main.ts#L150-L186","documentation":"Every request to this server must carry params as a plain object (not an array, string, number, or null); arrays and non-objects are rejected with -32602 Invalid params. This is stricter than bare JSON-RPC because handlers read named fields off params.","triggerScenarios":"Calling dispatch with params:[], params:'x', params:5, or params omitted and no default applied (dispatch does pass {} when params is undefined, but validateRequest rejects anything present but non-object).","commonSituations":"Clients modeling tool arguments as arrays, or serializing params to a JSON string before sending.","solutions":["Wrap arguments in an object: params:{...} not params:[...]","Double-check the JSON serializer is not flattening objects to strings"],"exampleFix":"// before\n{ jsonrpc: '2.0', id: 1, method: 'tools/list', params: [] }\n// after\n{ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {} }","handlingStrategy":"validation","validationCode":"if (!params || typeof params !== 'object' || Array.isArray(params)) params = {};","typeGuard":"function isJsonObject(v: unknown): v is Record<string, unknown> { \n  return typeof v === 'object' && v !== null && !Array.isArray(v); \n}","tryCatchPattern":null,"preventionTips":["Always send named-argument objects, never positional arrays","Type params as Record<string, unknown> in the client so the compiler blocks arrays"],"tags":["json-rpc","invalid-params","typescript"],"backgroundTag":"invalid-params","analyzedSha":"39ea8a1c6d0b61f071226eff7ede4d4105fed820","analyzedAt":"2026-08-26T03:13:46.626Z","schemaVersion":2},"datasetVersion":"2026-08-26T07:17:17.940Z"}