fix: honor stop option for ChatOpenAI Custom BaseOptions#6531
Conversation
ChatOpenAI Custom accepted BaseOptions JSON but forwarded every key as defaultHeaders. That made issue FlowiseAI#2499's stop parameter become an HTTP header instead of a ChatOpenAI model option, so the model never received the configured stop sequence. This keeps the change narrow: stop is promoted to ChatOpenAI fields, baseURL/defaultHeaders remain client configuration, and unknown BaseOptions keys continue to act as request headers for compatibility. Constraint: Flowise issue FlowiseAI#2499 reports stop supplied through ChatOpenAI Custom BaseOptions. Rejected: Add a new Stop Sequence input | an existing open PR explores that UI path, but it does not directly preserve the reported BaseOptions workflow. Rejected: Promote every BaseOptions key to model fields | too broad for a bugfix and could break users relying on custom headers. Confidence: high Scope-risk: narrow Reversibility: clean Directive: Do not broaden BaseOptions model-option promotion without explicit compatibility tests for request headers. Tested: pnpm.cmd --filter flowise-components test -- ChatOpenAICustom.test.ts --runInBand Tested: pnpm.cmd --filter flowise-components exec tsc --noEmit --pretty false Tested: pnpm.cmd --filter flowise-components exec eslint nodes/chatmodels/ChatOpenAICustom/ChatOpenAICustom.ts nodes/chatmodels/ChatOpenAICustom/ChatOpenAICustom.test.ts --ext ts --report-unused-disable-directives --max-warnings 0 Tested: pnpm.cmd --filter flowise-components build Tested: pnpm.cmd build; PORT=3000 pnpm.cmd start; GET / returned 200; GET /api/v1/ping returned pong Not-tested: Authenticated UI node-edit flow and live OpenAI-compatible API request. Related: FlowiseAI#2499
There was a problem hiding this comment.
Code Review
This pull request refactors the ChatOpenAICustom node to properly parse and extract stop, baseURL, and defaultHeaders from baseOptions, and adds corresponding unit tests. Feedback suggests adding validation to ensure parsedBaseOptions is a plain object before destructuring, which prevents potential runtime errors when handling invalid JSON inputs.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| let baseOptionsBaseURL: string | undefined | ||
| let baseOptionsDefaultHeaders: ICommonObject | undefined | ||
|
|
||
| if (parsedBaseOptions) { |
There was a problem hiding this comment.
If parsedBaseOptions is parsed as a non-object JSON value (such as a string or an array), destructuring it directly or using Object.keys on it can lead to unexpected behavior. To promote fail-fast behavior when handling potentially invalid data from external sources, we should throw an error if the input type is invalid, rather than silently skipping or returning a default value.
if (!parsedBaseOptions || typeof parsedBaseOptions !== 'object' || Array.isArray(parsedBaseOptions)) {
throw new Error('Invalid base options: expected a plain object');
}References
- When handling potentially invalid data from external sources (like an API response), prefer throwing an error for invalid input types rather than silently returning a default or empty value. This promotes fail-fast behavior.
Summary
ChatOpenAI CustomsoBaseOptions.stopis passed to LangChainChatOpenAIas a model option instead of being sent as an HTTP default header.baseURLanddefaultHeaders.Submission convention followed
fix: ...for bug-fix PRs.fix: honor stop option for ChatOpenAI Custom BaseOptionsfix:prefix is preferred for future commits in this repo; this branch currently has one already-pushed commit created before the convention audit was added to the Alaxise skill.bugfix/<short-slug>, matching FlowiseCONTRIBUTING.md.fix: FLOWISE-553, 598, 616(fix: FLOWISE-553, 598, 616 #6464),fix: FLOWISE-400, 543, 551(fix: FLOWISE-400, 543, 551 #6417),fix: flowise 370(fix: flowise 370 #6409),fix(models): correct chatMistralAI and chatCohere pricing by 1000x(fix(models): correct chatMistralAI and chatCohere pricing by 1000x #6393), andfix: access to invited workspace(fix: access to invited workspace #6360). FlowiseCONTRIBUTING.mdasks bug-fix branches to usebugfix/<Your New Bugfix>.Problem
Issue #2499 reports that Additional Parameters did not take effect for ChatOpenAI Custom when a user entered:
{ "stop": ["<|im_end|>"] }The current node parsed
baseOptionsand assigned the entire object toobj.configuration.defaultHeaders. That meantstopbecame a request header and never reachedChatOpenAIFields.stop.Why this matters
Flowise is positioned as a visual AI-agent builder. Chat model configuration is a core user path, especially for custom or OpenAI-compatible models. When advanced model parameters are accepted by the node UI but silently routed to the wrong place, users cannot reliably control model output and maintainers get support reports that are hard to diagnose.
The change is meaningful because it fixes a concrete user-reported bug with a small, reviewable diff and a regression test.
Roadmap / mission alignment
The repository README describes Flowise as "Build AI Agents, Visually." This fix supports that mission by making one of the visual chat model nodes honor a model-control parameter that users configure through the node.
Issue alignment is direct: #2499 is open and labeled
enhancement,good first issue, andhelp wanted. Maintainer/community discussion also points at this area of the ChatOpenAI nodes.What changed
packages/components/nodes/chatmodels/ChatOpenAICustom/ChatOpenAICustom.ts: parsesBaseOptionsinto model options and client configuration instead of treating every key as a default header.packages/components/nodes/chatmodels/ChatOpenAICustom/ChatOpenAICustom.test.ts: adds regression coverage forstop,baseURL, anddefaultHeaders.How it works
baseOptionsis still parsed the same way as before. After parsing:stopis assigned toobj.stop, which is the LangChainChatOpenAIFieldspath.baseURLanddefaultHeadersare preserved underobj.configuration.This keeps the reported fix narrow. It does not attempt to promote every arbitrary
BaseOptionskey into model fields.Local deployment evidence
pnpm.cmd install --frozen-lockfile,pnpm.cmd build,PORT=3000 pnpm.cmd starthttp://localhost:3000,http://localhost:3000/api/v1/pingmodel.fields.stopwasundefined./api/v1/pingreturnedpong, and the focused regression test passed.Verification
pnpm.cmd --filter flowise-components test -- ChatOpenAICustom.test.ts --runInBand: 2 tests passed.pnpm.cmd --filter flowise-components exec tsc --noEmit --pretty false: passed.pnpm.cmd --filter flowise-components exec eslint nodes/chatmodels/ChatOpenAICustom/ChatOpenAICustom.ts nodes/chatmodels/ChatOpenAICustom/ChatOpenAICustom.test.ts --ext ts --report-unused-disable-directives --max-warnings 0: passed.pnpm.cmd --filter flowise-components build: passed.pnpm.cmd build: passed.PORT=3000 pnpm.cmd start: server started and responded locally.git diff --check: passed before commit.Risks considered
stopis promoted as a model option because it is the reported parameter.Risks not fully covered
stopshould still be covered by existing LangChain/OpenAI behavior.Review focus
stopfromBaseOptionsis acceptable without adding a dedicatedStop Sequencefield to ChatOpenAI Custom.Follow-ups intentionally left out
Stop SequenceUI input to ChatOpenAI Custom.BaseOptions.Ownership report
Generated locally for contributor handoff and intentionally not linked from this public PR because it is not part of the repository diff.
Fixes #2499