Skip to content

fix(Google Gemini Node): Filter out undefined parts when processing API responses#28567

Merged
RomanDavydchuk merged 8 commits intomasterfrom
node-4822-community-issue-googlegemini-node-typeversion-11-crashes
Apr 27, 2026
Merged

fix(Google Gemini Node): Filter out undefined parts when processing API responses#28567
RomanDavydchuk merged 8 commits intomasterfrom
node-4822-community-issue-googlegemini-node-typeversion-11-crashes

Conversation

@RomanDavydchuk
Copy link
Copy Markdown
Contributor

@RomanDavydchuk RomanDavydchuk commented Apr 16, 2026

Summary

If Google's API response contained undefined parts, for some reason, the node would fail because 'functionCall' in p throws an error when p is undefined. This PR adds extra checks to make sure we properly filter out unwanted parts of the response

Related Linear tickets, Github issues, and Community forum posts

https://linear.app/n8n/issue/NODE-4822/community-issue-googlegemini-node-typeversion-11-crashes-with-cannot
Closes #28215

Review / Merge checklist

  • I have seen this code, I have run this code, and I take responsibility for this code.
  • PR title and summary are descriptive. (conventions)
  • Docs updated or follow-up ticket created.
  • Tests included.
  • PR Labeled with Backport to Beta, Backport to Stable, or Backport to v1 (if the PR is an urgent fix that needs to be backported)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 16, 2026

Performance Comparison

Comparing currentlatest master14-day baseline

docker-stats

Metric Current Latest Master Baseline (avg) vs Master vs Baseline Status
docker-image-size-runners 388.00 MB 388.00 MB 390.69 MB (σ 8.62) +0.0% -0.7%
docker-image-size-n8n 1280.00 MB 1280.00 MB 1277.44 MB (σ 12.68) +0.0% +0.2%

Idle baseline with Instance AI module loaded

Metric Current Latest Master Baseline (avg) vs Master vs Baseline Status
instance-ai-heap-used-baseline 187.44 MB 191.66 MB 187.42 MB (σ 1.77) -2.2% +0.0%
instance-ai-rss-baseline 347.58 MB 352.70 MB 367.22 MB (σ 21.72) -1.4% -5.3%

Memory consumption baseline with starter plan resources

Metric Current Latest Master Baseline (avg) vs Master vs Baseline Status
memory-rss-baseline 226.77 MB 295.84 MB 290.89 MB (σ 29.40) -23.3% -22.0% 🔴
memory-heap-used-baseline 115.20 MB 118.45 MB 115.30 MB (σ 1.79) -2.7% -0.1%
How to read this table
  • Current: This PR's value (or latest master if PR perf tests haven't run)
  • Latest Master: Most recent nightly master measurement
  • Baseline: Rolling 14-day average from master
  • vs Master: PR impact (current vs latest master)
  • vs Baseline: Drift from baseline (current vs rolling avg)
  • Status: ✅ within 1σ | ⚠️ 1-2σ | 🔴 >2σ regression

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 16, 2026

Codecov Report

❌ Patch coverage is 77.77778% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ors/GoogleGemini/actions/text/message.operation.ts 77.77% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@RomanDavydchuk RomanDavydchuk marked this pull request as ready for review April 16, 2026 09:32
@Joffcom Joffcom requested a review from michael-radency April 16, 2026 09:33
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 3 files

Architecture diagram
sequenceDiagram
    participant Engine as n8n Workflow Engine
    participant Node as Google Gemini Node
    participant GoogleAPI as Google Gemini API
    participant Tools as n8n Tools / Functions

    Engine->>Node: execute()
    
    loop Until Max Iterations
        Node->>GoogleAPI: Generate content request
        GoogleAPI-->>Node: GenerateContentResponse (JSON)

        Note over Node: NEW: Process Candidates safely<br/>(Handles undefined/null objects)

        Node->>Node: CHANGED: getToolCalls()<br/>Filter parts via isFunctionCallPart()
        
        alt Tool calls detected
            loop For each Tool Call
                Node->>Tools: Execute identified tool
                Tools-->>Node: Tool output
            end
            Note over Node: Add tool results to message history
        else No tool calls
            Note over Node: Break loop
        end
    end

    Note over Node: NEW: Build Final Response

    opt options.simplify & options.includeMergedResponse
        Node->>Node: CHANGED: Filter text parts via isTextPart()<br/>(Skips undefined parts to prevent crash)
    end

    Node-->>Engine: Return INodeExecutionData[]
Loading

Copy link
Copy Markdown
Contributor

@michael-radency michael-radency left a comment

Choose a reason for hiding this comment

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

LGTM, added some non-blocking comments

Comment on lines +552 to +555
contents.push.apply(
contents,
response.candidates.map((c) => c.content),
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

claude:
push.apply offers no performance advantage over spread in modern JS engines. Both translate to the same operation: passing array elements as individual arguments to push.

The old push.apply pattern came from pre-ES6 days when spread didn't exist. It was used as a workaround. Today, contents.push(...arr) is the idiomatic equivalent and compiles to the same bytecode in V8.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think this got changed because I ran eslint autofix, and we have a lint rule to prefer apply over spread

The reasoning: if the array being spread is very big, it can cause stack overflow, because each array item is converted into a function argument, therefor it takes a lot of memory on the stack

This doesn't apply here, because contents is always rather small, but I'll leave it like this to keep the linter happy

Comment on lines +734 to +735
it('should skip undefined parts when parsing tool calls', async () => {
executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

maybe better name
"should handle undefined entries in parts array"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agree, updated it

@n8n-assistant n8n-assistant Bot added the n8n team Authored by the n8n team label Apr 21, 2026
@RomanDavydchuk RomanDavydchuk added this pull request to the merge queue Apr 27, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Apr 27, 2026
@RomanDavydchuk RomanDavydchuk added this pull request to the merge queue Apr 27, 2026
Merged via the queue into master with commit 0aabee0 Apr 27, 2026
50 checks passed
@RomanDavydchuk RomanDavydchuk deleted the node-4822-community-issue-googlegemini-node-typeversion-11-crashes branch April 27, 2026 16:13
@n8n-assistant n8n-assistant Bot mentioned this pull request Apr 28, 2026
@n8n-assistant
Copy link
Copy Markdown
Contributor

n8n-assistant Bot commented Apr 28, 2026

Got released with n8n@2.19.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

n8n team Authored by the n8n team Released

Projects

None yet

2 participants