{"record":{"id":"7283f1164b93266c","repo":"CopilotKit/CopilotKit","slug":"missing-or-invalid-parameter-key","errorCode":null,"errorMessage":"Missing or invalid parameter '${key}'","messagePattern":"Missing or invalid parameter '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"packages/runtime/src/v2/runtime/endpoints/single-route-helpers.ts","lineNumber":100,"sourceCode":"  const method = validateMethod(jsonEnvelope.method);\n\n  return {\n    method,\n    params: jsonEnvelope.params,\n    body: jsonEnvelope.body,\n  };\n}\n\nexport function expectString(\n  params: Record<string, unknown> | undefined,\n  key: string,\n): string {\n  const value = params?.[key];\n  if (typeof value === \"string\" && value.trim().length > 0) {\n    return value;\n  }\n\n  throw createResponseError(`Missing or invalid parameter '${key}'`, 400);\n}\n\nexport function createJsonRequest(base: Request, body: unknown): Request {\n  if (body === undefined || body === null) {\n    throw createResponseError(\"Missing request body for JSON handler\", 400);\n  }\n\n  const headers = new Headers(base.headers);\n  headers.set(\"content-type\", \"application/json\");\n  headers.delete(\"content-length\");\n\n  const serializedBody = serializeJsonBody(body);\n\n  return new Request(base.url, {\n    method: \"POST\",\n    headers,\n    body: serializedBody,\n    signal: base.signal,","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/CopilotKit/CopilotKit/blob/68fbe97d87420bd84e8196965c71bd6e394a3f7a/packages/runtime/src/v2/runtime/endpoints/single-route-helpers.ts#L82-L118","documentation":"expectString(params, key) reads params[key] and requires a non-empty trimmed string; anything else (missing key, undefined, null, number, object, whitespace-only string) throws a 400 with the message 'Missing or invalid parameter \\'<key\\>'. It is used by resolveSingleRoute to validate envelope params before delegating to JSON handlers.","triggerScenarios":"Posting a method envelope whose params object omits a required key, passes a non-string value (e.g. threadId as a number), or passes a string of only whitespace. The key name in the message identifies exactly which parameter failed.","commonSituations":"Omitting required params like threadId or agentName when hand-crafting envelope payloads; client code passing coerced values (numbers, null) where IDs must be strings; version changes that introduce a new required parameter older clients don't send.","solutions":["Read the error message: the quoted key names the exact parameter to fix","Ensure every required parameter is a non-empty string (wrap numeric IDs with String(...) if needed)","Log the outgoing envelope on the client to spot missing/whitespace keys during development"],"exampleFix":"// before\n{ method: 'agent/run', params: { threadId: 12345 } } // -> 400 Missing or invalid parameter 'threadId'\n\n// after\n{ method: 'agent/run', params: { threadId: '12345' } }","handlingStrategy":"validation","validationCode":"// Mirror the library's rule before sending\nfunction expectString(params: Record<string, unknown>, key: string): string {\n  const v = params?.[key];\n  if (typeof v === 'string' && v.trim().length > 0) return v;\n  throw new Error(`Missing or invalid parameter '${key}'`);\n}\nconst threadId = expectString(envelope.params, 'threadId');","typeGuard":"const isNonEmptyString = (v: unknown): v is string =>\n  typeof v === 'string' && v.trim().length > 0;","tryCatchPattern":"const res = await fetch(url, opts);\nif (res.status === 400) {\n  const body = await res.json().catch(() => null);\n  const m = body?.error?.match(/parameter '(.+)'/);\n  if (m) throw new Error(`Fix param '${m[1]}' in the outgoing envelope`);\n}","preventionTips":["Wrap required params in a client-side expectString helper identical to the server's","Coerce IDs with String(...) at the boundary instead of relying on implicit typing","Log full outgoing envelopes in dev to catch missing or whitespace-only params"],"tags":["http-400","parameter-validation","request-body"],"backgroundTag":"request-validation-failed","analyzedSha":"68fbe97d87420bd84e8196965c71bd6e394a3f7a","analyzedAt":"2026-08-27T04:03:26.537Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}