OpenHands / OpenHands/enterprise
[Bug]: V1 Web UI connects to agent-server via dynamic host port behind reverse proxy (Traefik), causing persistent "Network Error" / conversation stuck
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 4
- Forks
- 2
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 101
Description
Is there an existing issue for the same bug?
- I have searched existing issues and this is not a duplicate.
Bug Description
Title: [Bug]: V1 Web UI connects to agent-server via dynamic host port behind reverse proxy (Traefik), causing persistent "Network Error" / conversation stuck
Is there an existing issue for the same bug?
I have searched the existing issues. Related/possibly duplicate: OpenHands/OpenHands#12519, OpenHands/OpenHands#12403, OpenHands/OpenHands#12229.
Describe the bug
When deploying OpenHands V1 behind a reverse proxy (Traefik, via Dokploy) on a VPS, the application loads correctly, conversations are created, sandboxes spawn successfully, and skills load — but the conversation never becomes usable. The UI shows "Network Error" in the Changes panel and the message input stays "Disconnected" / "Waiting for sandbox".
Backend logs are completely clean (all 200 OK, no errors after the auth fix below).
The root cause is visible in the browser DevTools Network tab: the frontend issues requests directly to the agent-server using a dynamic host port instead of routing them through the reverse-proxied domain. Example failed request URL:
https://openhands.example.com:42031/api/git/changes?path=%2Fworkspace%2Fproject
The port (42031) is the randomly-assigned host port Docker maps to the agent-server container's 8000. This port:
is not in DNS,
is not exposed/routed by Traefik (only 443 → app:3000 is),
changes on every conversation,
so the browser request fails with a CORS preflight failure / connection error → "Network Error".
This matches the architecture limitation already documented in OpenHands/OpenHands#12403 ("Bridge network uses dynamic host ports, making it incompatible with proxy patterns") and the symptom in OpenHands/OpenHands#12519 ("Web UI connects to runtime WebSocket via localhost:<random_port> instead of remote host").
Current behavior
App UI loads fine over https://openhands.example.com (Traefik → app container :3000).
A new conversation is created (POST /api/v1/app-conversations → 201).
agent-server container spawns and reports healthy; 50 skills load successfully.
Browser then tries to reach the agent-server directly at https://openhands.example.com:<dynamic_port>/... and fails.
WebSocket connections to the app domain succeed (Finished), but the direct-to-agent-server XHR/preflight requests fail.
Result: "Network Error" + "Disconnected", conversation unusable.
Expected behavior
When OH_WEB_URL / a reverse-proxy deployment is configured, the frontend should route all agent-server traffic through the main app domain (proxied by the app server), never directly to a dynamic host port. A reverse-proxy deployment should not require the browser to reach arbitrary host ports.
How to reproduce
Deploy OpenHands V1 via Docker Compose behind Traefik (Dokploy), exposing only the app on a domain with HTTPS (port 3000 internal).
Configure an LLM (Anthropic Claude) in Settings.
Start a new conversation ("Start from Scratch").
Observe "Network Error" / "Disconnected".
Open DevTools → Network: failed requests target https://:<dynamic_port>/api/git/changes?....
OpenHands Installation
Docker Compose (self-hosted), behind Traefik reverse proxy managed by Dokploy.
OpenHands Version
App image: docker.openhands.dev/openhands/openhands:latest (SDK v1.27.0)
Agent server image: ghcr.io/openhands/agent-server:1.27.0-python
Operating System
Debian (VPS), Docker / Dokploy stack.
Logs, error messages, screenshots
Browser DevTools (Network tab), failed request General section:
Request URL: https://openhands.example.com:42031/api/git/changes?path=%2Fworkspace%2Fproject
Referrer Policy: strict-origin-when-cross-origin
agent-server container inspect (dynamic port mapping):
"8000/tcp":[{"HostIp":"","HostPort":"33587"}],
"8001/tcp":[{"HostIp":"","HostPort":"57999"}],
"8011/tcp":[{"HostIp":"","HostPort":"44743"}],
"8012/tcp":[{"HostIp":"","HostPort":"43617"}]
Note: the agent-server containers are always created on the default bridge (172.17.0.x), even when the main app is attached to custom Docker networks — consistent with OpenHands/OpenHands#12229 (the dynamically-created oh-agent-server-* containers don't inherit the app's network / extra_hosts).
Additional context
To get this far, two non-documented fixes were required:
Webhook 401 Unauthorized: The agent-server signs webhook callbacks to the app (http://host.docker.internal:3000/api/v1/webhooks/...) using OH_SESSION_API_KEYS_0, but the app rejected them with 401 because it had no matching secret (no /.openhands/.jwt_secret). Setting a fixed JWT_SECRET env var on the app container resolved the 401s. It would help to document this for reverse-proxy / Compose deployments.
Dynamic-port problem (this issue): even with auth fixed and the conversation/skills working server-side, the browser cannot reach the agent-server because of the dynamic host port. APP_MODE=oss did not change this behavior. network_mode: host is not a viable workaround (breaks health checks per OpenHands/OpenHands#12229 / OpenHands/OpenHands#11907).
A reverse-proxy-friendly mode — where the app server proxies all agent-server/sandbox traffic under the main domain (e.g. /<conversation_id>/... paths) instead of the browser connecting to dynamic ports — would make V1 usable behind Traefik/nginx/Caddy, which is the standard self-hosting setup.
Expected Behavior
No response
Actual Behavior
No response
Steps to Reproduce
No response
OpenHands Installation Method
Other
If you selected "Other", please specify
No response
OpenHands Version
No response
Version Confirmation
- I have confirmed this bug exists on the LATEST version of OpenHands
Model Name
No response
Operating System
None
Browser (if using web UI)
No response
Logs and Error Messages
No response
Screenshots and Additional Context
No response
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The issue names /api/v1/app-conversations, /api/git/changes, and the app/agent-server Docker Compose boundary as entry points; start by tracing how the frontend builds agent-server URLs and how the app exposes proxy routes. Reproduce behind Traefik and inspect browser Network requests. Done means agent-server and sandbox traffic stays on the main HTTPS domain without dynamic host ports.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, python
- Domain
- backend-api-design, cloud, infrastructure
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100