Skip to content

fix: wrap kConnector call in try/catch to prevent client hang#4834

Open
veeceey wants to merge 1 commit intonodejs:mainfrom
veeceey:fix/issue-4697-connector-throw-hang
Open

fix: wrap kConnector call in try/catch to prevent client hang#4834
veeceey wants to merge 1 commit intonodejs:mainfrom
veeceey:fix/issue-4697-connector-throw-hang

Conversation

@veeceey
Copy link

@veeceey veeceey commented Feb 23, 2026

When client[kConnector]() throws synchronously (e.g. from tls.connect with a bad cert/key), the error goes unhandled and leaves the client in a bad state where all subsequent client.request() calls hang indefinitely.

This wraps the client[kConnector](...) invocation in a try/catch that performs the same cleanup as the error callback path — calling handleConnectError and client[kResume]() — so the client recovers properly and further requests can proceed.

Repro from the issue:

const client = new Client('https://example.com', {
  connect: { key: 'bad key', cert: 'bad cert' }
})

// First request throws, but client gets stuck
await client.request({ method: 'GET', path: '/' }).catch(() => {})

// This hangs forever without the fix
await client.request({ method: 'GET', path: '/' })

Tested locally — both requests now throw the expected error and the client stays usable.

Fixes #4697

When client[kConnector]() throws synchronously (e.g. from tls.connect
with bad cert/key), the error was unhandled and left the client in a
bad state where subsequent requests would hang indefinitely.

Wrapping the call in try/catch with the same cleanup as the error
callback (handleConnectError + kResume) restores proper error recovery.

Fixes: nodejs#4697
@veeceey
Copy link
Author

veeceey commented Feb 23, 2026

Manual test results

Tested with the repro from the issue:

$ node test-repro.js
First request error (expected): error:0480006C:PEM routines::no start line
Second request error (expected): error:0480006C:PEM routines::no start line
PASS: Both requests completed without hanging

Before the fix, the second request would hang indefinitely. Now both requests throw the expected TLS error and the client stays in a usable state.

Existing test suites pass:

  • client-connect.js — 1/1 pass
  • client-request.js — 47/47 pass
  • client-reconnect.js — 1/1 pass

@veeceey
Copy link
Author

veeceey commented Mar 10, 2026

bumping this one — is there anything on my end that needs updating before review?

@veeceey
Copy link
Author

veeceey commented Mar 12, 2026

gentle ping - would love to get some feedback on this when you get a chance

Copy link
Member

@metcoder95 metcoder95 left a comment

Choose a reason for hiding this comment

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

can you add some test to cover it

@codecov-commenter
Copy link

Codecov Report

❌ Patch coverage is 91.37931% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.19%. Comparing base (1867fb7) to head (ea83821).
⚠️ Report is 19 commits behind head on main.

Files with missing lines Patch % Lines
lib/dispatcher/client.js 91.37% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4834      +/-   ##
==========================================
- Coverage   93.19%   93.19%   -0.01%     
==========================================
  Files         109      109              
  Lines       34228    34233       +5     
==========================================
+ Hits        31900    31903       +3     
- Misses       2328     2330       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

Client.request will hang indefinitely if Client[kConnector] throws an error

3 participants