Skip to content

SSH tunnel cleanup can close a replacement connection #37896

Description

@Suzu1Dev

Bug Description

The SSH client manager can close a replacement connection when an old client emits a delayed event. Cleanup selects the current registration by the SSH configuration hash. A replacement client uses the same hash when its connection settings match.

The manager also retains the old client-to-hash mapping after cleanup. A later usage update from that old client can update the replacement client's idle timestamp.

A synchronous exception from Client.connect() can leave a rejected connection promise in the cache. Later calls with the same settings reuse the rejection instead of attempting a new connection.

Steps to Reproduce

Use a local unit test with mocked SSH transport. No external SSH server is required.

  1. Obtain client A from SSHClientsManager.getClient().
  2. Emit end on A to remove its registration.
  3. Obtain client B with the same connection settings.
  4. Emit close on A.
  5. Observe that the manager calls end on B and removes B from its cache.

The same sequence also fails with a delayed end or error event from A.

For idle tracking, call updateLastUsed(A) after B is registered. Observe that B's idle time changes.

For connection failure, make connect() throw synchronously. Call getClient() twice with the same settings. Observe that connect() runs only once because the rejected promise remains cached.

Expected Behavior

An event from A must only clean up A's registration. It must not close B or abort B's controller. Usage updates from a removed client must not change the replacement's idle time. A failed connection must be removed from the cache so a later call can attempt a new connection.

Debug Info

This is a source-level reproduction from n8n-io/n8n revision 909a6bc. It is not a report from a running n8n instance.

The expanded SSH unit suite contains 23 cases. With the original production file, 5 cases fail and 18 pass. With the proposed cleanup change, all 23 pass.

Affected source: packages/core/src/execution-engine/ssh-clients-manager.ts.

Operating System

macOS.

n8n Version

2.37.0 (source checkout).

Node.js Version

24.1.0. The test environment uses pnpm 11.25.0 and Vitest 4.1.9.

Database

Not applicable. The isolated reproduction uses mocked SSH transport and does not connect to a database.

Execution Mode

Not applicable. The reproduction runs the unit suite, not an n8n execution instance.

Hosting

Local source checkout. No cloud or self-hosted deployment was used.

Related Context

PR #16054 changed earlier SSH cleanup and idle tracking behavior. This report describes separate lifecycle cases. No claim is made that it resolves another open issue.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    status:in-linearIssue or PR is now in Linearstatus:team-assignedA team has been assigned the issue or PRteam:catsIssue is with the Cats team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions