{"record":{"id":"328a02605bd85596","repo":"n8n-io/n8n","slug":"the-value-in-the-extra-body-field-must-be-a-json","errorCode":null,"errorMessage":"The value in the \"Extra Body\" field must be a JSON object","messagePattern":"The value in the \"Extra Body\" field must be a JSON object","errorType":"exception","errorClass":"NodeOperationError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/nodes-langchain/nodes/llms/LMChatOpenAi/LmChatOpenAi.node.ts","lineNumber":822,"sourceCode":"\t\t\tif (options.responseFormat) modelKwargs.response_format = { type: options.responseFormat };\n\t\t\tif (options.reasoningEffort && ['low', 'medium', 'high'].includes(options.reasoningEffort)) {\n\t\t\t\tmodelKwargs.reasoning_effort = options.reasoningEffort;\n\t\t\t}\n\t\t}\n\n\t\tif (options.extraBody) {\n\t\t\tlet extraBody: Record<string, unknown>;\n\t\t\ttry {\n\t\t\t\textraBody = jsonParse<Record<string, unknown>>(options.extraBody);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new NodeOperationError(\n\t\t\t\t\tthis.getNode(),\n\t\t\t\t\t'The value in the \"Extra Body\" field is not valid JSON',\n\t\t\t\t\t{ itemIndex, description: error instanceof Error ? error.message : String(error) },\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!isPlainObject(extraBody)) {\n\t\t\t\tthrow new NodeOperationError(\n\t\t\t\t\tthis.getNode(),\n\t\t\t\t\t'The value in the \"Extra Body\" field must be a JSON object',\n\t\t\t\t\t{ itemIndex },\n\t\t\t\t);\n\t\t\t}\n\t\t\tObject.assign(modelKwargs, extraBody);\n\t\t}\n\n\t\tconst includedOptions = pick(options, [\n\t\t\t'frequencyPenalty',\n\t\t\t'maxTokens',\n\t\t\t'presencePenalty',\n\t\t\t'temperature',\n\t\t\t'topP',\n\t\t\t'baseURL',\n\t\t]);\n\n\t\tconst fields: ChatOpenAIFields = {","sourceCodeStart":804,"sourceCodeEnd":840,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/nodes-langchain/nodes/llms/LMChatOpenAi/LmChatOpenAi.node.ts#L804-L840","documentation":"Sibling to error 690: thrown after jsonParse succeeds but isPlainObject(extraBody) is false. OpenAI's request body expects a top-level object of key/value overrides, so a JSON array, number, string, or boolean is rejected even though it parses.","triggerScenarios":"User enters a JSON array, primitive, or string in 'Extra Body' — e.g. [\"a\",\"b\"], 0.5, true, or \"hello\". Each parses cleanly but isPlainObject returns false.","commonSituations":"Confusing extraBody with a list option; pasting a bare value; templating that emits an array literal; misunderstanding the field's purpose.","solutions":["Wrap the value in an object: {\"key\": value}.","Find the correct OpenAI parameter name for the intended override and use it as the object key.","Clear the field when no overrides are needed."],"exampleFix":"// before\noptions.extraBody = \"[\\\"a\\\", \\\"b\\\"]\"\n// after\noptions.extraBody = \"{\\\"stop\\\": [\\\"a\\\", \\\"b\\\"]}\"","handlingStrategy":"type-guard","validationCode":"if (options.extraBody) {\n  const v = JSON.parse(options.extraBody);\n  if (typeof v !== 'object' || v === null || Array.isArray(v)) {\n    throw new Error(\"'Extra Body' must be a JSON object\");\n  }\n}","typeGuard":"const isPlainObject = (v: unknown): v is Record<string, unknown> =>\n  typeof v === 'object' && v !== null && !Array.isArray(v);","tryCatchPattern":"// Validate shape after parsing; reject non-objects before submission.","preventionTips":["Always wrap extra keys in an object literal.","Document with a clear object example in the option description.","Add CI lint over workflows to flag non-object extraBody values."],"tags":["openai","llm","json","type-mismatch","configuration"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}