Skip to content

[Bug]: memory_search remote embeddings fail with ENOTFOUND when env proxy is configured — withRemoteHttpResponse skips TRUSTED_ENV_PROXY mode #52162

@XIYBHK

Description

@XIYBHK

Bug type

Behavior bug (incorrect output/state without crash)

Summary

withRemoteHttpResponse() in the memory remote embeddings path does not check hasProxyEnvConfigured() before calling fetchWithSsrFGuard(), causing it to default to strict mode which performs local DNS pre-resolution via resolvePinnedHostnameWithPolicy(). In proxy environments (e.g. Clash TUN/fake-IP, corporate proxies), this DNS lookup fails with getaddrinfo ENOTFOUND before the request ever reaches the proxy, even though proxy-routed requests via the OpenAI SDK succeed on the same machine.

Steps to reproduce

  1. Configure an HTTP/HTTPS proxy via environment variables (HTTPS_PROXY, HTTP_PROXY, or ALL_PROXY).
  2. Use a proxy setup where local DNS cannot resolve the embedding provider hostname (e.g. Clash TUN fake-IP mode, or a corporate proxy with DNS-over-proxy).
  3. Configure a remote embedding provider (e.g. api.ohmygpt.com/v1 or any OpenAI-compatible endpoint).
  4. Run:
openclaw memory status --deep --agent main
openclaw memory search --agent main --query "test"
  1. Observe getaddrinfo ENOTFOUND <hostname> and Embeddings: unavailable.

Expected behavior

When environment proxy variables are configured, withRemoteHttpResponse() should use withTrustedEnvProxyGuardedFetchMode() to set the fetch mode to TRUSTED_ENV_PROXY, causing fetchWithSsrFGuard() to skip local DNS pre-resolution and use EnvHttpProxyAgent() directly — the same behavior already implemented for other proxy-aware code paths in the codebase.

Actual behavior

withRemoteHttpResponse() calls fetchWithSsrFGuard() without setting a mode, which defaults to STRICT. In strict mode, fetchWithSsrFGuard() always calls resolvePinnedHostnameWithPolicy()dns.lookup() before making the HTTP request. This local DNS lookup fails in proxy environments where DNS resolution must go through the proxy, producing:

Error: getaddrinfo ENOTFOUND api.ohmygpt.com

Meanwhile, on the same machine in the same shell session, OpenClaw's own OpenAI SDK calls to the same endpoint succeed — confirming the proxy works and the issue is isolated to the memory embeddings code path.

OpenClaw version

2026.3.13 (61d171a)

Operating system

Windows 11 Pro 10.0.22631

Install method

npm global

Model

openai/text-embedding-3-small (remote embedding provider)

Provider / routing chain

openclaw -> env HTTP proxy (Clash TUN) -> remote OpenAI-compatible embedding endpoint

Additional provider/model setup details

# Environment
HTTPS_PROXY=http://127.0.0.1:7890 (Clash TUN with fake-IP mode)

# Embedding config in openclaw agent config
models.providers.openai.baseUrl = "https://api.ohmygpt.com/v1"
memorySearch.remote.model = "text-embedding-3-small"

The same proxy + endpoint combination works when OpenClaw makes regular OpenAI SDK calls (e.g. chat completions), because those paths correctly use proxy-aware fetch. Only the memory embeddings path fails.

Logs, screenshots, and evidence

# Failing path (memory embeddings)
$ openclaw memory status --deep --agent main
Embeddings: unavailable
Error: getaddrinfo ENOTFOUND api.ohmygpt.com

# Working path (same machine, same proxy, same endpoint)
# OpenClaw's own OpenAI SDK calls to api.ohmygpt.com/v1 → OK, returns 1536-dim vectors

Root cause trace in source:

withRemoteHttpResponse(params)          # src/memory/post-json.ts or similar
  → fetchWithSsrFGuard({ url, init, policy })   # no mode set → defaults to STRICT
    → resolveGuardedFetchMode(params)            # returns STRICT (no mode field)
    → resolvePinnedHostnameWithPolicy(hostname)  # does dns.lookup() → ENOTFOUND

The fix already exists in the codebase for other callers. For example, src/memory/embeddings-remote-*.ts in some build outputs already has the corrected pattern. The issue is that withRemoteHttpResponse() was not updated to use it.

Correct pattern (already present in some bundle copies):

async function withRemoteHttpResponse(params) {
    const useEnvProxy = hasProxyEnvConfigured();
    const request = useEnvProxy ? withTrustedEnvProxyGuardedFetchMode({
        url: params.url,
        init: params.init,
        policy: params.ssrfPolicy,
        auditContext: params.auditContext ?? "memory-remote"
    }) : {
        url: params.url,
        init: params.init,
        policy: params.ssrfPolicy,
        auditContext: params.auditContext ?? "memory-remote"
    };
    const { response, release } = await fetchWithSsrFGuard(request);
    // ...
}

Impact and severity

  • Affected: All users running OpenClaw with env proxy configured (HTTP_PROXY/HTTPS_PROXY/ALL_PROXY) in environments where local DNS cannot resolve the embedding provider hostname (Clash TUN fake-IP, corporate forward proxies, WSL with host-side proxy, etc.)
  • Severity: High — completely blocks memory search functionality; Embeddings: unavailable
  • Frequency: 100% reproducible when the proxy + DNS condition is met
  • Consequence: memory_search tool and memory status --deep are non-functional; agents lose access to vector memory search entirely

Additional information

Note on build artifact duplication: withRemoteHttpResponse() is inlined by the bundler (rolldown) into multiple dist chunks. In 2026.3.13, we found 7 copies across different bundles — some already had the proxy fix, others did not. The source-level fix is a single-location change, but all bundle copies need to be consistent after build.

Affected bundles in 2026.3.13 (for reference):

  • reply-Bm8VrLQh.js — gateway agent tool path (missing fix)
  • auth-profiles-DDVivXkv.js — alternate auth bundle (missing fix)
  • discord-CcCLMjHw.js — discord channel path (missing fix)
  • auth-profiles-DRjqKE3G.js — CLI path (had fix)
  • model-selection-*.js — (had fix)
  • plugin-sdk/thread-bindings-*.js — (had fix)

Workaround: Manually patch withRemoteHttpResponse() in the affected dist bundles to add the hasProxyEnvConfigured() check as shown above.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions