{"record":{"id":"639fed68ec45b426","repo":"mastra-ai/mastra","slug":"argument-key-is-required","errorCode":null,"errorMessage":"Argument \"${key}\" is required","messagePattern":"Argument \"(.+?)\" is required","errorType":"validation","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"packages/server/src/server/handlers/utils.ts","lineNumber":18,"sourceCode":"import type { MastraFGAPermissionInput } from '@mastra/core/auth/ee';\nimport type { RequestContext } from '@mastra/core/di';\nimport { MastraMemory } from '@mastra/core/memory';\nimport { MASTRA_RESOURCE_ID_KEY, MASTRA_THREAD_ID_KEY } from '../constants';\nimport { MastraFGAPermissions } from '../fga-permissions';\nimport { HTTPException } from '../http-exception';\n\n// Validation helper\nexport function validateBody(body: Record<string, unknown>) {\n  const errorResponse = Object.entries(body).reduce<Record<string, string>>((acc, [key, value]) => {\n    if (!value) {\n      acc[key] = `Argument \"${key}\" is required`;\n    }\n    return acc;\n  }, {});\n\n  if (Object.keys(errorResponse).length > 0) {\n    throw new HTTPException(400, { message: Object.values(errorResponse)[0] });\n  }\n}\n\n/**\n * sanitizes the body by removing disallowed keys.\n * @param body body to sanitize\n * @param disallowedKeys keys to remove from the body\n */\nexport function sanitizeBody(body: Record<string, unknown>, disallowedKeys: string[]) {\n  for (const key of disallowedKeys) {\n    if (key in body) {\n      delete body[key];\n    }\n  }\n}\n\nexport function parsePerPage(\n  value: string | undefined,","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/utils.ts#L1-L36","documentation":"validateBody collects every required body key that is missing and throws a 400 with the first missing argument's message. The generate/stream route handlers use it to fail fast when the caller omitted required fields (e.g. messages) before agent execution begins.","triggerScenarios":"POSTing to generate/stream routes (GENERATE_AGENT_ROUTE, GENERATE_LEGACY_ROUTE, STREAM_GENERATE_ROUTE/LEGACY, STREAM_UNTIL_IDLE, STREAM_NETWORK) with a body missing required keys such as `messages`, or sending no/empty body, or wrong Content-Type so the body parses to nothing.","commonSituations":"Forgetting the JSON body entirely, sending form data where JSON is expected, misspelling a key (e.g. `message` instead of `messages`), or a client SDK version sending the old body shape after a server upgrade.","solutions":["Include all required keys in the JSON body — for generate routes typically `messages: [{ role, content }]`.","Set Content-Type: application/json and send a valid JSON payload.","Compare against the current route contract in packages/server handlers or the client SDK types for required fields.","Log the outgoing body client-side to catch misspelled/absent keys."],"exampleFix":"// before\nawait fetch('/api/agents/assistant/generate', { method: 'POST', body: JSON.stringify({ prompt: 'hi' }) });\n// after\nawait fetch('/api/agents/assistant/generate', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ messages: [{ role: 'user', content: 'hi' }] }),\n});","handlingStrategy":"validation","validationCode":"function validateGenerateBody(body: unknown): asserts body is { messages: Array<{ role: string; content: string }> } {\n  const b = body as any;\n  if (!b || typeof b !== 'object') throw new Error('Request body must be a JSON object');\n  if (!Array.isArray(b.messages) || b.messages.length === 0) {\n    throw new Error('messages array is required in the request body');\n  }\n}","typeGuard":"function hasRequiredArgs(body: unknown, required: string[]): body is Record<string, unknown> {\n  return !!body && typeof body === 'object' &&\n    required.every(k => (body as Record<string, unknown>)[k] !== undefined && (body as Record<string, unknown>)[k] !== null);\n}","tryCatchPattern":"try {\n  const res = await fetch('/api/agents/assistant/generate', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) });\n  if (res.status === 400) {\n    const msg = await res.text();\n    throw new Error(`Bad request: ${msg}`);\n  }\n  return await res.json();\n} catch (e) { throw e; }","preventionTips":["Validate request bodies against the route schema before sending.","Always set Content-Type: application/json.","Keep client payload types in sync with server route contracts after upgrades.","Check key spelling (messages vs message) in a unit test."],"tags":["http-400","request-body","validation","rest-api"],"backgroundTag":"missing-request-parameter","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}