Skip to content

fix(core): Release LS trace clients on run finalization (no-changelog)#28254

Merged
OlegIvaniv merged 2 commits intomasterfrom
fix/release-trace-clients-on-run-finalization
Apr 10, 2026
Merged

fix(core): Release LS trace clients on run finalization (no-changelog)#28254
OlegIvaniv merged 2 commits intomasterfrom
fix/release-trace-clients-on-run-finalization

Conversation

@OlegIvaniv
Copy link
Copy Markdown
Contributor

@OlegIvaniv OlegIvaniv commented Apr 9, 2026

Summary

The module-level traceClients Map in langsmith-tracing.ts was only cleaned when a root run finished successfully via finishRun(). If a run was aborted, timed out, or the finishRun HTTP call failed, the Client and its entire RunTree hierarchy stayed in the Map indefinitely.

Add releaseTraceClient() that unconditionally deletes the entry, and call it from:

  • finalizeMessageTraceRoot (normal message run completion)
  • finalizeDetachedTraceRun (background task completion)
  • deleteTraceContextsForThread (safety net on thread deletion)

Measured impact (parallel workflow building benchmark: 3 tabs × 3 rounds)

Metric Before After
Heap leak (post-cleanup − baseline) +152 MB +80 MB
Round-over-round growth (R2→R3) +75 MB +6 MB
RunTree objects after cleanup 127 near 0 (expected)

The remaining ~80 MB delta is one-time lazy loading (node type catalog, source maps, Zod schemas) that loads on first workflow build and stays flat across subsequent rounds.

Related Linear tickets, Github issues, and Community forum posts

Review / Merge checklist

  • 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)
  • I have seen this code, I have run this code, and I take responsibility for this code.

…angelog)

The module-level traceClients Map in langsmith-tracing.ts was only
cleaned when a root run finished successfully via finishRun(). If a run
was aborted, timed out, or the finishRun HTTP call failed, the Client
and its entire RunTree hierarchy stayed in the Map indefinitely.

Add releaseTraceClient() that unconditionally deletes the entry, and
call it from:
- finalizeMessageTraceRoot (normal message run completion)
- finalizeDetachedTraceRun (background task completion)
- deleteTraceContextsForThread (safety net on thread deletion)

Each call site uses a finally block so cleanup happens regardless of
whether the trace HTTP calls succeed or fail.

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
@OlegIvaniv OlegIvaniv requested a review from Cadiac April 9, 2026 13:47
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 9, 2026

Codecov Report

❌ Patch coverage is 0% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...cli/src/modules/instance-ai/instance-ai.service.ts 0.00% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

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 Svc as InstanceAiService
    participant Tracing as LangSmith Tracing Module
    participant Cache as traceClients (Map)
    participant LS as LangSmith API

    Note over Svc, LS: Run Finalization (Success or Failure)

    Svc->>Tracing: finalizeMessageTraceRoot / finalizeDetachedTraceRun
    
    rect rgb(240, 240, 240)
        Note right of Svc: try block
        Svc->>LS: finishRun (via SDK)
    end

    alt on Error
        LS-->>Svc: Error (Timeout/Network)
        Svc->>Svc: Log Error
    else on Success
        LS-->>Svc: 200 OK
    end

    Note right of Svc: finally block
    Svc->>Tracing: NEW: releaseTraceClient(traceId)
    Tracing->>Cache: NEW: delete(traceId)
    Note over Cache: GC can now reclaim Client<br/>and RunTree hierarchy

    Note over Svc, Cache: Thread Deletion (Safety Net)
    
    Svc->>Svc: deleteTraceContextsForThread(threadId)
    loop for each run context
        Svc->>Tracing: NEW: releaseTraceClient(traceId)
        Tracing->>Cache: NEW: delete(traceId)
    end
Loading

@Cadiac Cadiac changed the title fix(instance-ai): Release LS trace clients on run finalization (no-changelog) fix(core): Release LS trace clients on run finalization (no-changelog) Apr 9, 2026
@n8n-assistant n8n-assistant Bot added core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team labels Apr 9, 2026
Copy link
Copy Markdown
Contributor

@Cadiac Cadiac left a comment

Choose a reason for hiding this comment

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

👍 👍

@OlegIvaniv OlegIvaniv added this pull request to the merge queue Apr 10, 2026
Merged via the queue into master with commit 320a4b2 Apr 10, 2026
52 of 53 checks passed
@OlegIvaniv OlegIvaniv deleted the fix/release-trace-clients-on-run-finalization branch April 10, 2026 09:54
@n8n-assistant
Copy link
Copy Markdown
Contributor

n8n-assistant Bot commented Apr 14, 2026

Got released with n8n@

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

Labels

core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team Released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants