Skip to content

🔌 fix: Isolate Code-Server HTTP Agents to Prevent Socket Pool Contamination#12311

Merged
danny-avila merged 4 commits into
devfrom
fix/code-executor-socket-hangup
Mar 19, 2026
Merged

🔌 fix: Isolate Code-Server HTTP Agents to Prevent Socket Pool Contamination#12311
danny-avila merged 4 commits into
devfrom
fix/code-executor-socket-hangup

Conversation

@danny-avila

@danny-avila danny-avila commented Mar 19, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes a "socket hang up" after ~5 seconds on Node 19+ when the code executor processes file attachments, and hardens the surrounding infrastructure with a shared agent module, proxy parity, a missing upload timeout, and regression test coverage.

  • Introduces dedicated http.Agent / https.Agent instances with keepAlive: false for all four axios call sites targeting CODE_BASEURL (getCodeOutputDownloadStream, uploadCodeEnvFile, processCodeOutput, getSessionInfo), preventing tainted sockets from re-entering the global pool and destroying active node-fetch requests in CodeExecutor.
  • Extracts the shared agent construction and its explanatory JSDoc into a new agents.js module, eliminating the DRY violation that would have existed across crud.js and process.js.
  • Migrates process.js from a raw require('axios') call to createAxiosInstance() from @librechat/api, aligning proxy configuration behavior with crud.js.
  • Adds a 120s timeout to uploadCodeEnvFile, which was the only code-server axios call without one.
  • Adds crud.spec.js covering getCodeOutputDownloadStream and uploadCodeEnvFile with agent option assertions, timeout verification, URL correctness, success/error paths, and entity_id query parameter behavior.
  • Extends process.spec.js with a socket pool isolation describe block that asserts the exact agent instances, their types, and keepAlive: false are forwarded to axios for processCodeOutput.
  • Updates process-traversal.spec.js and existing process.spec.js mocks to reflect the createAxiosInstance() migration.

Change Type

  • Bug fix (non-breaking change which fixes an issue)

Testing

Ran the existing and new unit tests from the api workspace:

cd api && npx jest server/services/Files/Code

Covers:

  • crud.spec.js — agent isolation, keepAlive: false, timeout, URL, entity_id param, success/error paths for both CRUD functions
  • process.spec.js — full existing suite (atomic claim, image/non-image processing, size limits, fallback behavior, usage counters, metadata) plus the new socket pool isolation block asserting agents are forwarded correctly
  • __tests__/process-traversal.spec.js — path traversal protection, unaffected by the changes

To reproduce the underlying bug manually: run LibreChat on Node 20+ with a code executor configured, attach a file to a conversation, and trigger code execution. Without this fix, the download or session-info request will hang up after ~5 seconds. With it, requests complete cleanly.

Test Configuration:

  • Node.js v20.19.0+
  • Code executor (CODE_BASEURL) configured and reachable
  • File attachment present in the conversation before triggering execution

Checklist

  • My code adheres to this project's style guidelines
  • I have performed a self-review of my own code
  • I have commented in any complex areas of my code
  • My changes do not introduce new warnings
  • I have written tests demonstrating that my changes are effective or that my feature works
  • Local unit tests pass with my changes

Closes #12298

Prevents socket hang up after 5s on Node 19+ when code executor has
file attachments. follow-redirects (axios dep) leaks `socket.destroy`
as a timeout listener on TCP sockets; with Node 19+ defaulting to
keepAlive: true, tainted sockets re-enter the global pool and destroy
active node-fetch requests in CodeExecutor after the idle timeout.

Uses dedicated http/https agents with keepAlive: false for all axios
calls targeting CODE_BASEURL in crud.js and process.js.

Closes #12298
Copilot AI review requested due to automatic review settings March 19, 2026 18:46

Copilot AI left a comment

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.

Pull request overview

This PR addresses a Node.js (19+/23+) “socket hang up after 5s” failure in the code executor when file attachments trigger axios (follow-redirects) requests to the code-server, by isolating those axios requests from the default/global HTTP agent pool.

Changes:

  • Introduces dedicated http.Agent / https.Agent instances with keepAlive: false for code-server axios calls.
  • Wires these dedicated agents into axios requests in both the code output processing path and code file CRUD helpers.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
api/server/services/Files/Code/process.js Adds dedicated HTTP(S) agents and applies them to axios calls used during code output processing/session info retrieval.
api/server/services/Files/Code/crud.js Adds dedicated HTTP(S) agents and applies them to axios calls for code output download streams and file uploads.

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

Comment thread api/server/services/Files/Code/crud.js
Comment thread api/server/services/Files/Code/process.js Outdated
Comment thread api/server/services/Files/Code/crud.js Outdated
Comment thread api/server/services/Files/Code/crud.js Outdated
Comment thread api/server/services/Files/Code/process.js
- Move duplicated agent construction from crud.js and process.js into
  a shared agents.js module to eliminate DRY violation
- Switch process.js from raw `require('axios')` to `createAxiosInstance()`
  for proxy configuration parity with crud.js
- Fix import ordering in process.js (agent constants no longer split imports)
- Add 120s timeout to uploadCodeEnvFile (was the only code-server call
  without a timeout)
@danny-avila danny-avila force-pushed the fix/code-executor-socket-hangup branch 2 times, most recently from 51a9d6b to 1bce032 Compare March 19, 2026 19:35
- Add crud.spec.js covering getCodeOutputDownloadStream and
  uploadCodeEnvFile (agent options, timeout, URL, error handling)
- Add socket pool isolation tests to process.spec.js asserting
  keepAlive:false agents are forwarded to axios
- Update process.spec.js mocks for createAxiosInstance() migration
@danny-avila danny-avila force-pushed the fix/code-executor-socket-hangup branch from 1bce032 to 93e8b70 Compare March 19, 2026 19:49
@danny-avila danny-avila changed the title 🔧 fix: Isolate HTTP agents for code-server axios requests 🔌 fix: Isolate Code-Server HTTP Agents to Prevent Socket Pool Contamination Mar 19, 2026
Relocate agents.js from api/server/services/Files/Code/ to
packages/api/src/utils/code.ts per workspace conventions. Consumers
now import codeServerHttpAgent/codeServerHttpsAgent from @librechat/api.
@danny-avila danny-avila force-pushed the fix/code-executor-socket-hangup branch from 807515c to 899c1d2 Compare March 19, 2026 20:08
@danny-avila danny-avila merged commit 39f5f83 into dev Mar 19, 2026
9 checks passed
@danny-avila danny-avila deleted the fix/code-executor-socket-hangup branch March 19, 2026 20:17
mstlaur1 pushed a commit to mstlaur1/LibreChat that referenced this pull request Mar 25, 2026
…nation (danny-avila#12311)

* 🔧 fix: Isolate HTTP agents for code-server axios requests

Prevents socket hang up after 5s on Node 19+ when code executor has
file attachments. follow-redirects (axios dep) leaks `socket.destroy`
as a timeout listener on TCP sockets; with Node 19+ defaulting to
keepAlive: true, tainted sockets re-enter the global pool and destroy
active node-fetch requests in CodeExecutor after the idle timeout.

Uses dedicated http/https agents with keepAlive: false for all axios
calls targeting CODE_BASEURL in crud.js and process.js.

Closes danny-avila#12298

* ♻️ refactor: Extract code-server HTTP agents to shared module

- Move duplicated agent construction from crud.js and process.js into
  a shared agents.js module to eliminate DRY violation
- Switch process.js from raw `require('axios')` to `createAxiosInstance()`
  for proxy configuration parity with crud.js
- Fix import ordering in process.js (agent constants no longer split imports)
- Add 120s timeout to uploadCodeEnvFile (was the only code-server call
  without a timeout)

* ✅ test: Add regression tests for code-server socket isolation

- Add crud.spec.js covering getCodeOutputDownloadStream and
  uploadCodeEnvFile (agent options, timeout, URL, error handling)
- Add socket pool isolation tests to process.spec.js asserting
  keepAlive:false agents are forwarded to axios
- Update process.spec.js mocks for createAxiosInstance() migration

* ♻️ refactor: Move code-server agents to packages/api

Relocate agents.js from api/server/services/Files/Code/ to
packages/api/src/utils/code.ts per workspace conventions. Consumers
now import codeServerHttpAgent/codeServerHttpsAgent from @librechat/api.
jcbartle pushed a commit to jcbartle/LibreChat that referenced this pull request May 11, 2026
…nation (danny-avila#12311)

* 🔧 fix: Isolate HTTP agents for code-server axios requests

Prevents socket hang up after 5s on Node 19+ when code executor has
file attachments. follow-redirects (axios dep) leaks `socket.destroy`
as a timeout listener on TCP sockets; with Node 19+ defaulting to
keepAlive: true, tainted sockets re-enter the global pool and destroy
active node-fetch requests in CodeExecutor after the idle timeout.

Uses dedicated http/https agents with keepAlive: false for all axios
calls targeting CODE_BASEURL in crud.js and process.js.

Closes danny-avila#12298

* ♻️ refactor: Extract code-server HTTP agents to shared module

- Move duplicated agent construction from crud.js and process.js into
  a shared agents.js module to eliminate DRY violation
- Switch process.js from raw `require('axios')` to `createAxiosInstance()`
  for proxy configuration parity with crud.js
- Fix import ordering in process.js (agent constants no longer split imports)
- Add 120s timeout to uploadCodeEnvFile (was the only code-server call
  without a timeout)

* ✅ test: Add regression tests for code-server socket isolation

- Add crud.spec.js covering getCodeOutputDownloadStream and
  uploadCodeEnvFile (agent options, timeout, URL, error handling)
- Add socket pool isolation tests to process.spec.js asserting
  keepAlive:false agents are forwarded to axios
- Update process.spec.js mocks for createAxiosInstance() migration

* ♻️ refactor: Move code-server agents to packages/api

Relocate agents.js from api/server/services/Files/Code/ to
packages/api/src/utils/code.ts per workspace conventions. Consumers
now import codeServerHttpAgent/codeServerHttpsAgent from @librechat/api.
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.

Code executor: socket hang up after 5s when files are attached (Node.js v23 + follow-redirects leak)

2 participants