fix(server): don't deep-clone live node instances in resolveVariables (fixes OpenAI embeddings/RAG 500)#6478
Conversation
resolveVariables() deep-clones the ending node's data, which includes its already-built live `instance`. Deep-cloning a cached `openai` SDK client (or any native handle: gRPC channel, FAISS store) copies the prototype but bypasses the constructor, so the clone fails openai v6's private- member brand checks in OpenAI.buildURL -- every OpenAI-embeddings/RAG chatflow 500s at buildChatflow with "Cannot read private member from an object whose class did not declare it". Chat models are unaffected (they don't cache a client into the cloned data). Omit `instance` from the deep clone and re-attach the original (generalizes the previously-removed FAISS-only workaround to all live instances). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request prevents deep-cloning of a node's live instance (such as an OpenAI SDK client) during variable resolution in packages/server/src/utils/index.ts to avoid runtime errors with private-member brand checks. The feedback suggests using a nullish check (!= null) when re-assigning the instance and applying the same omit pattern to another cloneDeep call in buildFlow to prevent similar issues.
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.
…uard - Use `!= null` (repo idiom) instead of a truthy check when re-attaching the instance. - Apply the same omit-and-reattach to the cloneDeep in buildFlow(): a node re-evaluated in an agentflow loop already has `.instance` populated, so deep-cloning it there hits the same private-member brand error. (resolveVariables' guard alone can't help — buildFlow clones first.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@gemini-code-assist, can you please re-review with the latest fixes? |
There was a problem hiding this comment.
Code Review
This pull request modifies packages/server/src/utils/index.ts to prevent deep-cloning a node's live instance property, which bypasses constructors and breaks ES private-member brand checks. The reviewer suggests using native ES6 object destructuring instead of lodash's omit to exclude the instance property before deep-cloning, which improves performance, readability, and avoids an extra lodash import.
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.
Exclude `instance` via `const { instance, ...rest } = data` and deep-clone `rest`, dropping the
extra lodash `omit` import (more idiomatic/performant). Re-attach the original instance with a
`!= null` check. Applies to both resolveVariables() and buildFlow().
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@gemini-code-assist, can you please re-review with the latest fixes? |
There was a problem hiding this comment.
Code Review
This pull request modifies packages/server/src/utils/index.ts to prevent deep-cloning a node's live instance property, which bypasses constructors and breaks ES private-member brand checks (such as in the OpenAI SDK). Instead, instance is excluded from the deep clone and re-attached afterward. The reviewer suggested using instance !== undefined instead of instance != null to ensure that null values are preserved and re-attached correctly, preventing potential bugs where null is coerced to undefined.
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.
…ined - The destructured-clone is `Omit<INodeData,'instance'>`, so re-assigning `.instance` failed tsc (TS2339). Cast `cloneDeep(rest) as INodeData` to restore the optional `instance` field. - Use `instance !== undefined` (per review) so an explicit `null` instance is preserved. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@gemini-code-assist, can you please re-review with the latest fixes? |
There was a problem hiding this comment.
Code Review
This pull request prevents deep-cloning a node's live instance property (such as an OpenAI SDK client) in buildFlow and resolveVariables to avoid breaking ES private-member brand checks. The reviewer recommended adding a defensive guard in resolveVariables to handle potential nullish values of reactFlowNodeData and prevent runtime errors.
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.
Return early if reactFlowNodeData is nullish (the destructuring would otherwise throw a less clear TypeError than the prior cloneDeep on edge-case/external callers). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@gemini-code-assist, can you please re-review with the latest fixes? |
There was a problem hiding this comment.
Code Review
This pull request prevents deep-cloning of live instance properties (such as OpenAI SDK clients) within buildFlow and resolveVariables to avoid breaking ES private-member brand checks. Instead, the instance is excluded from cloneDeep and re-attached afterward. Feedback highlights a potential issue where reactFlowNodes is still deep-cloned at the start of buildFlow (line 548), which could break live instances before they reach the loop, and suggests safely preserving them there as well.
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.
Description
resolveVariables()deep-clones the ending node's data, which includes its already-built live.instance. Deep-cloning a cachedopenaiSDK client (or any native handle: gRPC channel, FAISS store) copies the prototype but bypasses the constructor, so the clone failsopenaiv6's private-member brand checks inOpenAI.buildURL→ every OpenAI-embeddings / RAG chatflow 500s atbuildChatflowwithCannot read private member from an object whose class did not declare it. Chat models are unaffected (they don't cache a client into the cloned data).Fix: omit
instancefrom the deep clone and re-attach the original. This generalizes a workaround Flowise previously had for FAISS only (since removed).resolveVariablesonly needs to resolveinputstemplates — it has no reason to copy the live instance.Fixes #6477.
Root cause (minimal repro, no server needed)
How I tested
On a local Flowise (
3.1.2) running an in-memory RAG chatflow (Plain Text → Recursive Splitter → OpenAI Embedding → In-Memory Vector Store → Retrieval QA Chain):POST /api/v1/prediction/:id→ 500buildChatflow - Cannot read private member ....Checklist
main.