Skip to content

fix(server): don't deep-clone live node instances in resolveVariables (fixes OpenAI embeddings/RAG 500)#6478

Open
dkindlund wants to merge 5 commits into
FlowiseAI:mainfrom
dkindlund:fix/resolvevariables-clone-instance
Open

fix(server): don't deep-clone live node instances in resolveVariables (fixes OpenAI embeddings/RAG 500)#6478
dkindlund wants to merge 5 commits into
FlowiseAI:mainfrom
dkindlund:fix/resolvevariables-clone-instance

Conversation

@dkindlund
Copy link
Copy Markdown
Contributor

Description

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).

Fix: omit instance from the deep clone and re-attach the original. This generalizes a workaround Flowise previously had for FAISS only (since removed). resolveVariables only needs to resolve inputs templates — it has no reason to copy the live instance.

Fixes #6477.

Root cause (minimal repro, no server needed)

const { OpenAIEmbeddings } = require('@langchain/openai')   // openai v6 underneath
const { cloneDeep } = require('lodash')
const e = new OpenAIEmbeddings({ openAIApiKey: process.env.OPENAI_API_KEY })
await e.embedQuery('warm up')        // primes & caches e.client (branded by the constructor)
await cloneDeep(e).embedQuery('x')   // throws: Cannot read private member ... at OpenAI.buildURL

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):

  • Before: POST /api/v1/prediction/:id → 500 buildChatflow - Cannot read private member ....
  • After: the same flow returns correct answers across multiple questions.
  • No regressions: chat-model chains and tool-calling-agent flows behave exactly as before.

Checklist

  • Targets main.
  • Minimal, focused change (1 file, +7 −2).
  • Backward compatible (FAISS's previous behavior is now the default for all instances).

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>
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread packages/server/src/utils/index.ts Outdated
…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>
@dkindlund
Copy link
Copy Markdown
Contributor Author

@gemini-code-assist, can you please re-review with the latest fixes?

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread packages/server/src/utils/index.ts Outdated
Comment thread packages/server/src/utils/index.ts Outdated
Comment thread packages/server/src/utils/index.ts Outdated
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>
@dkindlund
Copy link
Copy Markdown
Contributor Author

@gemini-code-assist, can you please re-review with the latest fixes?

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread packages/server/src/utils/index.ts Outdated
Comment thread packages/server/src/utils/index.ts Outdated
…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>
@dkindlund
Copy link
Copy Markdown
Contributor Author

@gemini-code-assist, can you please re-review with the latest fixes?

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread packages/server/src/utils/index.ts
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>
@dkindlund
Copy link
Copy Markdown
Contributor Author

@gemini-code-assist, can you please re-review with the latest fixes?

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread packages/server/src/utils/index.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] OpenAI embeddings / RAG chatflow 500s at buildChatflow: "Cannot read private member from an object whose class did not declare it"

1 participant