Skip to content

fix: prevent context switch race and clear warning interval on shutdown#616

Closed
ashsolei wants to merge 1 commit intoczlonkowski:mainfrom
ashsolei:fix/context-switch-race-and-interval-leak
Closed

fix: prevent context switch race and clear warning interval on shutdown#616
ashsolei wants to merge 1 commit intoczlonkowski:mainfrom
ashsolei:fix/context-switch-race-and-interval-leak

Conversation

@ashsolei
Copy link

@ashsolei ashsolei commented Mar 1, 2026

Problem

Two issues in the HTTP server session management:

1. Context Switch Race Condition (HIGH)

When concurrent HTTP requests trigger switchSessionContext for the same session with different contexts:

  • Request A acquires the lock and begins switching
  • Request B finds the lock, awaits it, then returns without performing its own switch
  • B's context update is silently discarded
  • The session operates against A's context — B's request reads/writes to the wrong n8n instance

This is a data integrity issue in multi-tenant deployments where requests for different n8n instances can interleave on the same session.

2. Warning Interval Leak (LOW)

When using the default auth token in non-production, a setInterval (every 5 minutes) was started but the handle was never stored or cleared. On shutdown(), this timer continues firing, holding references to the logger and server instance, preventing garbage collection.

Fix

  1. Context switch: After awaiting the existing lock, re-enter switchSessionContext instead of returning. The re-entered call will check if the context still differs (via JSON.stringify comparison in performContextSwitch) and apply B's switch if needed. This is safe because the lock is released before re-entry.

  2. Interval leak: Store the interval handle in this.warningTimer and clear it in shutdown() alongside the existing cleanup timer.

Validation

  • HTTP server unit tests: 30 passed, 12 skipped, 0 failures
  • TypeScript compilation: only pre-existing module declaration warnings
  • Changes limited to src/http-server-single-session.ts (13 insertions, 3 deletions)

Two issues in http-server-single-session.ts:

1. switchSessionContext race condition: when concurrent requests trigger
   context switches for the same session, request B awaited A's lock
   then returned without performing its own switch. B's context update
   was silently discarded, causing the session to operate against the
   wrong n8n instance. Fix: re-enter switchSessionContext after awaiting
   the lock so B's switch is evaluated and applied if still needed.

2. Default token warning setInterval leaked: the interval handle was
   never stored, so shutdown() could not clear it. This prevented GC
   of the server instance and caused timer callbacks to fire after
   shutdown. Fix: store the interval in this.warningTimer and clear
   it in shutdown().
Copilot AI review requested due to automatic review settings March 1, 2026 05:29
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes two session-management issues in SingleSessionHTTPServer that can affect correctness and resource cleanup during HTTP server operation, especially in multi-tenant “shared session” mode.

Changes:

  • Prevents dropped context updates by re-entering switchSessionContext() after awaiting an in-flight context switch.
  • Stores the default-token warning setInterval handle and clears it during shutdown() to avoid a timer leak.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +309 to +313
// to perform our own switch (the previous switch may have been
// for a different context than what we need)
await existingLock;
return;
// Re-enter instead of returning — our context may differ from what was just set
return this.switchSessionContext(sessionId, newContext);
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

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

There are unit tests covering the session cleanup timer lifecycle, but there doesn’t appear to be a regression test for the multi-tenant shared-mode context switch race this change is fixing (concurrent calls for the same sessionId with different contexts). Please add a test that triggers two overlapping context switches and asserts the final session/server instanceContext matches the last request (i.e., no update is dropped after waiting on an existing lock).

Copilot uses AI. Check for mistakes.
Comment on lines +1425 to +1429
// Stop default token warning timer
if (this.warningTimer) {
clearInterval(this.warningTimer);
this.warningTimer = null;
}
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

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

The interval is now stored and cleared on shutdown, but there doesn’t seem to be test coverage that the default-token warning interval is actually started (in non-production) and then cleared during shutdown. Adding a unit test with fake timers/spies that sets the default AUTH_TOKEN, calls start(), then shutdown(), and asserts clearInterval was invoked for warningTimer would prevent this leak from regressing.

Copilot uses AI. Check for mistakes.
@ashsolei
Copy link
Author

ashsolei commented Mar 1, 2026

Closing — will maintain fixes in a private mirror instead. Thank you for the review.

@ashsolei ashsolei closed this Mar 1, 2026
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.

2 participants