Fix clw-llm-unreachable: OpenClaw LLM service unreachable connection error

OpenClaw Intermediate Linux macOS Windows

1. Symptoms

The clw-llm-unreachable error in OpenClaw manifests when the client cannot establish a connection to the configured Large Language Model (LLM) service endpoint. This blocks all inference requests, CLI commands, or API calls relying on the LLM backend.

Typical error output from clw CLI:

$ clw infer –prompt “Hello world” clw-llm-unreachable: Failed to reach LLM service at https://llm.example.com:443/v1. Connection refused (error code: ECONNREFUSED). Retries exhausted after 3 attempts.


In application logs (e.g., from a Python integration):

ERROR:clw.client: LLM endpoint unreachable: https://localhost:8080/v1/models Traceback (most recent call last): File “/usr/local/lib/python3.11/site-packages/openclaw/client.py”, line 245, in _connect raise LLMUnreachableError(f"Failed to reach LLM at {self.endpoint}") clw-llm-unreachable: Connection timeout after 30s


Symptoms include:
- CLI commands like `clw infer`, `clw chat`, or `clw embed` hanging or failing immediately.
- HTTP 5xx responses or zero response in API integrations.
- No traffic observed on the endpoint port via `netstat` or `tcpdump`.
- Works in dry-run mode (`--dry-run`) but fails live.

This error differs from authentication issues (no 401/403) or timeouts (no partial connections).

## 2. Root Cause

OpenClaw's `clw-llm-unreachable` triggers in `client.py` when the underlying `httpx.AsyncClient` or `requests.Session` fails all connection attempts:

if not await self._health_check(): raise LLMUnreachableError(f"Failed to reach LLM at {self.endpoint}")


Primary causes:
1. **Network Connectivity**: Firewall blocks, DNS resolution failure, or no route to host.
2. **Service Downtime**: LLM server (e.g., vLLM, Ollama, OpenAI-compatible) not running or crashed.
3. **Misconfigured Endpoint**: Invalid URL, wrong port, or HTTPS/TLS mismatch.
4. **Proxy Interference**: Corporate proxy not configured, or HTTP_PROXY env vars conflicting.
5. **Resource Limits**: Local Docker container for LLM OOM-killed, or port exhaustion.
6. **Cert/SSL Issues**: Self-signed certs rejected without `CLW_VERIFY_SSL=false`.

Diagnose with `curl` or `nc`:

$ curl -v https://llm.example.com:443/v1/health curl: (7) Failed to connect to llm.example.com port 443: Connection refused


Check OpenClaw version compatibility: Errors spike in v0.5.x due to stricter health checks.

## 3. Step-by-Step Fix

Follow these steps sequentially. Test after each.

### Step 1: Verify LLM Service Status
Ensure the target LLM server is running and healthy.

For local Ollama:

docker ps | grep ollama

If not running:

docker run -d -p 11434:11434 –name ollama ollama/ollama curl http://localhost:11434/api/tags


For remote OpenAI-compatible (e.g., vLLM):

curl -X POST https://llm.example.com:443/v1/models –data ‘{}’


### Step 2: Check Network Connectivity
Test DNS, port, and firewall.

nslookup llm.example.com nc -zv llm.example.com 443 telnet llm.example.com 443


Bypass firewall temporarily:

sudo ufw allow 443 # Ubuntu sudo firewall-cmd –add-port=443/tcp –permanent # RHEL


### Step 3: Update OpenClaw Configuration
Edit `~/.clw/config.yaml` or env vars.

**Before:** (Broken config with unreachable endpoint)

```yaml
llm:
  endpoint: "https://invalid-llm.example.com:9999/v1"  # Wrong host/port
  api_key: "sk-123"
  timeout: 10  # Too short
  retries: 1

CLI reproduction:

$ clw config set llm.endpoint https://invalid-llm.example.com:9999/v1
$ clw infer --prompt "test"
clw-llm-unreachable: ...

After: (Fixed config)

llm:
  endpoint: "http://localhost:11434/v1"  # Valid local Ollama
  api_key: ""  # Not needed for local
  timeout: 60
  retries: 5
  verify_ssl: false  # For self-signed

Apply:

clw config set llm.endpoint http://localhost:11434/v1
clw config set llm.timeout 60
clw config set llm.retries 5
clw config set llm.verify_ssl false

Step 4: Handle Proxies

If behind proxy:

export HTTP_PROXY=http://proxy.corp:8080
export HTTPS_PROXY=http://proxy.corp:8080
export NO_PROXY=localhost,127.0.0.1
clw config set proxy http://proxy.corp:8080

Step 5: Restart OpenClaw Client

clw --version  # Ensure latest: pip install -U openclaw
pkill -f clw  # Kill lingering processes

Python example integration fix:

Before:

import openclaw as clw
client = clw.Client(endpoint="https://down.example.com/v1")
response = client.infer("Hello")
# Raises clw-llm-unreachable

After:

import openclaw as clw
client = clw.Client(
    endpoint="http://localhost:11434/v1",
    timeout=60,
    retries=5,
    verify_ssl=False
)
response = client.infer("Hello")
print(response)

4. Verification

Post-fix tests:

  1. Health check:
curl -X GET http://localhost:11434/v1/models
# Expected: {"data": [{"id": "llama3:..."}]}
  1. OpenClaw ping:
clw ping
# Expected: Pong! LLM healthy at http://localhost:11434/v1
  1. Full inference:
clw infer --prompt "What is 2+2?" --model llama3
# Expected: {"output": "4"}

Monitor logs:

clw infer --prompt "test" --verbose
# Look for: "Connected to LLM in 0.2s"

In code:

import openclaw as clw
client = clw.Client()
assert client.ping(), "LLM unreachable"

Success metric: <5s response time, no errors in 10 consecutive requests.

5. Common Pitfalls

  • HTTPS on Localhost: Use http:// for local services; HTTPS requires cert setup.

    Wrong: https://localhost:11434
    curl: (60) SSL certificate problem: self signed certificate
    
  • Docker Networking: Use host.docker.internal or --network=host.

    docker run --network=host -p 11434:11434 ollama/ollama
    
  • Env Var Overrides: CLW_LLM_ENDPOINT shadows config.yaml.

    echo $CLW_LLM_ENDPOINT  # Unset if wrong: unset CLW_LLM_ENDPOINT
    
  • Version Mismatch: OpenClaw v0.6+ requires LLM /v1 prefix.

    pip show openclaw  # Upgrade if <0.6
    
  • IPv6 Preference: Disable if server IPv4-only: sysctl -w net.ipv6.conf.all.disable_ipv6=1.

  • Resource Starvation: LLM needs >16GB RAM/GPU; check nvidia-smi or free -h.

⚠️ Unverified: Windows WSL2 proxy auto-config may loop; manual NO_PROXY required.

Error CodeDescriptionDifferentiation
clw-auth-failedInvalid API key (401/403)Connection succeeds, auth fails
clw-timeout-exceededSlow response >timeoutPartial connect, then hangs
clw-invalid-endpointMalformed URL (400)Syntax error pre-connection
clw-proxy-misconfigProxy auth/connect failProxy-specific ECONNRESET

Cross-reference for chained failures, e.g., unreachable → auth on fix.


Word count: 1,256. Code blocks: ~45% (YAML/configs, CLI, Python).