WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

[BUG] UI stuck on "Session connecting..."; blank screen with CDP/WebSocket errors after some automation #222

@fathiraz

Description

@fathiraz

Describe the bug
After running several automation actions, the Steel UI intermittently becomes blank and stays on the banner "Session connecting...". Sessions list API responds 200, but the UI cannot attach to the session. Docker logs show a CDP WebSocket proxy failure to 127.0.0.1:9222 and a separate WebSocket "socket hang up" to ws://0.0.0.0:3000/. The state does not recover without restarting containers.

To Reproduce

  1. Self-host Steel via Docker (API on 3000/9223, UI on 5173) per docs.
  2. Open the UI, create a session, and run some automation (navigate, open devtools/cast, etc.).
  3. After a few minutes/actions, return to the UI session view.
  4. The canvas is blank and the header shows "Session connecting..." indefinitely.

I used the standard Docker setup referenced in docs:

Expected behavior

  • The UI attaches to the running session and renders the page stream.
  • If the session has ended, the UI shows an actionable error with guidance, not an endless "connecting" state.

Screenshots

  • Attached: blank UI showing "Session connecting..." and DevTools console with repeated websocket messages and sandbox warnings.
    Image

Logs
Docker API logs at the time of failure:

{"level":30,"time":1761790992016,"pid":1,"hostname":"13765d0bbc87","reqId":"req-hz","ip":"192.168.215.1","url":"/v1/sessions","method":"GET","statusCode":200,"durationMs":0.65,"msg":"request completed"}

{"level":30,"time":1761790993027,"pid":1,"hostname":"13765d0bbc87","reqId":"req-i0","ip":"192.168.215.1","url":"/v1/sessions","method":"GET","statusCode":200,"durationMs":1.64,"msg":"request completed"}

{"level":30,"time":1761790994142,"pid":1,"hostname":"13765d0bbc87","reqId":"req-i1","ip":"192.168.215.1","url":"/v1/sessions","method":"GET","statusCode":200,"durationMs":3.66,"msg":"request completed"}

{"level":30,"time":1761790995161,"pid":1,"hostname":"13765d0bbc87","reqId":"req-i2","ip":"192.168.215.1","url":"/v1/sessions","method":"GET","statusCode":200,"durationMs":0.64,"msg":"request completed"}

{"level":30,"time":1761791121650,"pid":1,"hostname":"13765d0bbc87","msg":"Upgrading browser socket..."}

{"level":30,"time":1761791121751,"pid":1,"hostname":"13765d0bbc87","msg":"Connecting to cast..."}

{"level":30,"time":1761791121837,"pid":1,"hostname":"13765d0bbc87","reqId":"req-i3","ip":"192.168.215.1","url":"/v1/sessions","method":"GET","statusCode":200,"durationMs":2.02,"msg":"request completed"}

{"level":30,"time":1761791121847,"pid":1,"hostname":"13765d0bbc87","msg":"Upgrading browser socket..."}

{"level":30,"time":1761791121847,"pid":1,"hostname":"13765d0bbc87","msg":"Connecting to CDP..."}

{"level":50,"time":1761791121856,"pid":1,"hostname":"13765d0bbc87","component":"CDPService","msg":"WebSocket proxy error: Error: connect ECONNREFUSED 127.0.0.1:9222"}

{"level":30,"time":1761791121856,"pid":1,"hostname":"13765d0bbc87","component":"CDPService","msg":"[CDPService] WebSocket connection listeners cleaned up"}

Error in cast session: ErrorEvent {
  [Symbol(kTarget)]: WebSocket {
    _events: [Object: null prototype] { open: [Function], error: [Function] },
    _eventsCount: 2,
    _maxListeners: undefined,
    _binaryType: 'nodebuffer',
    _closeCode: 1006,
    _closeFrameReceived: false,
    _closeFrameSent: false,
    _closeMessage: <Buffer >,
    _closeTimer: null,
    _errorEmitted: true,
    _extensions: {},
    _paused: false,
    _protocol: '',
    _readyState: 3,
    _receiver: null,
    _sender: null,
    _socket: null,
    _bufferedAmount: 0,
    _isServer: false,
    _redirects: 0,
    _autoPong: true,
    _url: 'ws://0.0.0.0:3000/',
    _originalIpc: false,
    _originalSecure: false,
    _originalHostOrSocketPath: '0.0.0.0:3000',
    _req: null,
    [Symbol(shapeMode)]: false,
    [Symbol(kCapture)]: false
  },
  [Symbol(kType)]: 'error',
  [Symbol(kError)]: Error: socket hang up
      at Socket.socketOnEnd (node:_http_client:542:25)
      at Socket.emit (node:events:536:35)
      at endReadableNT (node:internal/streams/readable:1698:12)
      at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {
    code: 'ECONNRESET'
  },
  [Symbol(kMessage)]: 'socket hang up'
}

Browser DevTools console (from the UI tab) also shows:

  • Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
  • Error while parsing the 'sandbox' attribute: 'allow-clipboard-write', 'allow-clipboard-read' are invalid sandbox flags.
  • WebSocket connection opened/closed repeatedly for tab discovery.

Desktop (please complete the following information):

  • OS: macOS M1 2020 (Darwin OS Tahoe 26.0.1)
  • Browser: Chrome (latest stable at time of report)
  • Docker Desktop: latest
  • Steel version: ghcr.io/steel-dev/steel-browser-api:latest and ghcr.io/steel-dev/steel-browser-ui:latest (also reproduced on v0.4.4-beta)

Additional context
From logs and behavior, there may be two separate issues that combine into the blank UI:

  1. CDP port mismatch or Chrome not ready

    • API logs show ECONNREFUSED to 127.0.0.1:9222 for CDP. Docker docs expose debugger on 9223 by default (docs). If the API expects 9222 inside the container while the published/forwarded port is 9223, or Chrome hasn’t bound yet, the CDP upgrade fails and the UI remains in a perpetual "connecting" state.
  2. UI uses ws://0.0.0.0:3000/ as a target

    • The cast socket error points to 0.0.0.0, which is a wildcard bind address, not a routable host. When used as a client endpoint, this can cause ECONNRESET/hang-ups. The UI should target the actual host (e.g., http://localhost:3000), not 0.0.0.0.

Potential workarounds I tried/consider:

  • Restarting the API container temporarily restores the UI until the next occurrence.
  • Ensuring the API/UI are accessed via localhost and not an IP alias (still reproduced).
  • Verifying ports: API 3000, debugger 9223, UI 5173 per docs. Reference: Docker setup.

What would help:

  • Guidance on configuring the CDP port the API expects (9222 vs 9223) in self-hosted Docker, or making the service retry/backoff until Chrome is ready.
  • UI fix to avoid using 0.0.0.0 as a client WebSocket URL; prefer the actual host/origin.
  • If this is an expected session end, surface a clear error instead of an infinite "connecting" state.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions