AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

ChatOpenRouter Creates Fresh Httpx Clients Per Instantiation Causing Connection Leak

langchain-openrouter's ChatOpenRouter constructs a new httpx.Client and httpx.AsyncClient for each instance without default-client caching, leading to linear growth in TLS connections when models are instantiated per request (e.g., LangGraph factory graphs, FastAPI dependency injection). This mirrors a bug fixed for AzureChatOpenAI in langchain-openai.

highConfidence 95%LangchainAffected V0.2.3

Origin Analysis

Missing default httpx client caching in ChatOpenRouter.__init__. The code creates new httpx clients for every instance and passes them to the OpenRouter SDK; when no custom client is supplied, the SDK may also create its own clients per instance. No shared module-level client is used, and clients are not closed on instance teardown, causing socket/TLS pool leakage.
1. Install langchain-openrouter==0.2.3 and set a valid OPENROUTER_API_KEY. 2. Run the provided Python snippet that creates 20 ChatOpenRouter instances in a loop, calls ainvoke, deletes the instance, and calls gc.collect(). 3. Observe that the number of ESTABLISHED TCP connections to openrouter.ai grows linearly and does not return to baseline after deletion.

Fixing Code Block

Edge Case Audit

Shared cached clients are thread-safe for requests but not for mutation of client properties after creation. If any code modifies the returned client's headers or other attributes, it will affect all instances using the shared client. Users needing per-instance customization should pass their own http_client/http_async_client. The extra_headers branch still creates new clients per instance and may leak if used frequently; this can be addressed later with a header-keyed cache. Rollback: if this change introduces unexpected shared-state issues, revert to the previous code or instruct users to pass explicit clients.

Ecosystem Topology