{"record":{"id":"4fe2656f5d833f4f","repo":"FlowiseAI/Flowise","slug":"invalid-json-in-the-chatopenai-s-baseoptions-ex-4fe265","errorCode":null,"errorMessage":"Invalid JSON in the ChatOpenAI's BaseOptions: ${exception}","messagePattern":"Invalid JSON in the ChatOpenAI's BaseOptions: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/nodes/chatmodels/ChatOpenAICustom/ChatOpenAICustom.ts","lineNumber":160,"sourceCode":"            openAIApiKey,\n            apiKey: openAIApiKey,\n            streaming: streaming ?? true\n        }\n\n        if (maxTokens) obj.maxTokens = parseInt(maxTokens, 10)\n        if (topP) obj.topP = parseFloat(topP)\n        if (frequencyPenalty) obj.frequencyPenalty = parseFloat(frequencyPenalty)\n        if (presencePenalty) obj.presencePenalty = parseFloat(presencePenalty)\n        if (timeout) obj.timeout = parseInt(timeout, 10)\n        if (cache) obj.cache = cache\n\n        let parsedBaseOptions: any | undefined = undefined\n\n        if (baseOptions) {\n            try {\n                parsedBaseOptions = typeof baseOptions === 'object' ? baseOptions : JSON.parse(baseOptions)\n            } catch (exception) {\n                throw new Error(\"Invalid JSON in the ChatOpenAI's BaseOptions: \" + exception)\n            }\n        }\n\n        if (basePath) await checkDenyList(basePath)\n\n        if (basePath || parsedBaseOptions) {\n            obj.configuration = {\n                baseURL: basePath,\n                defaultHeaders: parsedBaseOptions\n            }\n        }\n\n        const model = new ChatOpenAI(obj)\n        return model\n    }\n}\n\nmodule.exports = { nodeClass: ChatOpenAICustom_ChatModels }","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/chatmodels/ChatOpenAICustom/ChatOpenAICustom.ts#L142-L178","documentation":"ChatOpenAICustom is a thin sibling of ChatOpenAI and reproduces the same BaseOptions JSON-parse guard. When the BaseOptions string fails JSON.parse, the SyntaxError is re-thrown with the ChatOpenAI's-label message. (Note: the label says 'ChatOpenAI' even though this node is ChatOpenAICustom — a copy-paste artifact, but the failure mode is identical.)","triggerScenarios":"The ChatOpenAICustom node's BaseOptions field holds malformed JSON; same parser failures as [92]. Reachable only when baseOptions is a truthy string.","commonSituations":"Users pointing at a custom OpenAI-compatible endpoint paste a headers object with JSON syntax errors; confusion between the ChatOpenAI and ChatOpenAICustom nodes leads to fixing the wrong node; docs example copied with formatting artifacts.","solutions":["JSON-lint the BaseOptions string and save the corrected version.","If the message says 'ChatOpenAI' but you are on ChatOpenAICustom, remember the label is shared — fix BaseOptions on the ChatOpenAICustom node specifically.","Pass an object rather than a string when constructing programmatically to bypass parsing.","Start from a minimal valid object and add headers one at a time."],"exampleFix":"// before\n{ \"X-Key\": 'abc', } // mixed quotes + trailing comma -> throws [93]\n\n// after\n{ \"X-Key\": \"abc\" }","handlingStrategy":"validation","validationCode":"function parseBaseOptions(raw) {\n  if (!raw) return undefined\n  if (typeof raw === 'object') return raw\n  try { return JSON.parse(raw) }\n  catch (e) { throw new Error(`ChatOpenAICustom BaseOptions JSON invalid: ${e.message}`) }\n}\nconst parsedBaseOptions = parseBaseOptions(nodeData.inputs?.baseOptions)","typeGuard":"function isHeadersObject(v: unknown): v is Record<string, string> {\n  if (typeof v !== 'object' || v === null || Array.isArray(v)) return false\n  return Object.values(v).every(x => typeof x === 'string')\n}","tryCatchPattern":"try {\n  return await initChatOpenAICustom(nodeData, options)\n} catch (e) {\n  // Note: error label says 'ChatOpenAI' even on the Custom node\n  if (e.message.includes(\"Invalid JSON in the ChatOpenAI's BaseOptions\")) {\n    throw new Error('Fix BaseOptions JSON on the ChatOpenAICustom node (label is shared with ChatOpenAI).')\n  }\n  throw e\n}","preventionTips":["Remember the error label is shared — fix BaseOptions on whichever node you are actually using.","JSON-lint the value before saving.","Use object inputs when constructing programmatically.","Add a UI-side validator to catch this before save."],"tags":["json","configuration","validation","openai-custom","default-headers"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}