{"record":{"id":"b7b1b3292d4c28c1","repo":"usememos/memos","slug":"missing-required-request-body-body","errorCode":null,"errorMessage":"missing required request body \"body\"","messagePattern":"missing required request body \"body\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/router/mcp/adapter.go","lineNumber":72,"sourceCode":"\t\tif parameter.In != \"query\" {\n\t\t\tcontinue\n\t\t}\n\t\tvalue, ok := arguments[parameter.Name]\n\t\tif !ok || value == nil {\n\t\t\tcontinue\n\t\t}\n\t\tquery.Set(parameter.Name, valueToString(value))\n\t}\n\tif encoded := query.Encode(); encoded != \"\" {\n\t\tpath += \"?\" + encoded\n\t}\n\n\tvar body io.Reader\n\tif operation.RequestBody != nil {\n\t\tbodyValue, ok := arguments[\"body\"]\n\t\tif !ok || bodyValue == nil {\n\t\t\tif operation.RequestBody.Required {\n\t\t\t\treturn nil, errors.New(`missing required request body \"body\"`)\n\t\t\t}\n\t\t\tbodyValue = map[string]any{}\n\t\t}\n\n\t\tdata, err := json.Marshal(bodyValue)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"failed to marshal request body\")\n\t\t}\n\t\tbody = bytes.NewReader(data)\n\t}\n\n\treq := httptest.NewRequest(operation.Method, path, body).WithContext(ctx)\n\tif body != nil {\n\t\treq.Header.Set(\"Content-Type\", \"application/json\")\n\t}\n\tif authorization != \"\" {\n\t\treq.Header.Set(\"Authorization\", authorization)\n\t}","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/server/router/mcp/adapter.go#L54-L90","documentation":"Thrown by the MCP-to-OpenAPI adapter in server/router/mcp/adapter.go when an OpenAPI operation declares a required request body but the MCP tool call arguments do not include a \"body\" key (or it is JSON null). The adapter maps MCP tool arguments onto an HTTP request; a required body must arrive as arguments[\"body\"]. The error surfaces to the MCP client as a tool error result.","triggerScenarios":"Calling an MCP tool derived from a POST/PUT/PATCH OpenAPI operation whose requestBody.required is true without supplying the \"body\" argument, or passing body: null in the tool arguments.","commonSituations":"LLM agents omitting the body object for create/update tools; tool schemas that describe body properties at the top level instead of nested under \"body\"; optional-looking tool arguments for endpoints that actually require a payload.","solutions":["Include a \"body\" object in the tool call arguments matching the operation's request schema, e.g. {\"body\": {\"content\": \"...\", \"visibility\": \"PRIVATE\"}}","Check the tool's input schema (derived from the OpenAPI spec) to confirm the body shape before invoking","If the operation should accept an empty payload, fix the OpenAPI definition so requestBody is not required"],"exampleFix":"// before (MCP tool call)\nawait client.callTool({ name: \"memos_createMemo\", arguments: {} });\n// after\nawait client.callTool({ name: \"memos_createMemo\", arguments: { body: { content: \"hello\" } } });","handlingStrategy":"validation","validationCode":"// Before calling the MCP tool, confirm the operation requires a body and include it.\nconst requiresBody = operation.requestBody?.required === true;\nconst args = { ...toolArgs };\nif (requiresBody && (args.body === undefined || args.body === null)) {\n  throw new Error(`Tool ${operation.operationId} requires a \"body\" argument`);\n}","typeGuard":"const hasRequiredBody = (args: Record<string, unknown>): boolean =>\n  args.body !== undefined && args.body !== null;","tryCatchPattern":"// The adapter returns tool errors inside CallToolResult (isError), not as thrown errors:\nconst result = await client.callTool({ name, arguments });\nif (result.isError) {\n  const text = result.content?.[0]?.text ?? \"\";\n  if (text.includes('missing required request body')) {\n    // re-invoke with a body built from the tool's input schema\n  }\n}","preventionTips":["Always inspect the tool's inputSchema before invoking; keep request payload under a \"body\" key","When generating tool calls from LLM output, validate arguments against inputSchema first"],"tags":["mcp","openapi","request-body","validation"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}