[GH-ISSUE #24207] issue: Safari cannot establish WebSocket on 0.9.2 (direct port, no reverse proxy) #58896

Closed
opened 2026-05-06 00:22:38 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @josemodena on GitHub (Apr 28, 2026).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/24207

Check Existing Issues

  • I have searched for any existing and/or related issues.
  • I have searched for any existing and/or related discussions.
  • I have also searched in the CLOSED issues AND CLOSED discussions and found no related items (your issue might already be addressed on the development branch!).
  • I am using the latest version of Open WebUI.

Installation Method

Docker

Open WebUI Version

v0.9.2

Ollama Version (if applicable)

No response

Operating System

macOS 26

Browser (if applicable)

Safari 26.3.1 (fails); Chrome (works)

Confirmation

  • I have read and followed all instructions in README.md.
  • I am using the latest version of both Open WebUI and Ollama.
  • I have included the browser console logs.
  • I have included the Docker container logs.
  • I have provided every relevant configuration, setting, and environment variable used in my setup.
  • I have clearly listed every relevant configuration, custom setting, environment variable, and command-line option that influences my setup (such as Docker Compose overrides, .env values, browser settings, authentication configurations, etc).
  • I have documented step-by-step reproduction instructions that are precise, sequential, and leave nothing to interpretation. My steps:
  • Start with the initial platform/version/OS and dependencies used,
  • Specify exact install/launch/configure commands,
  • List URLs visited, user input (incl. example values/emails/passwords if needed),
  • Describe all options and toggles enabled or changed,
  • Include any files or environmental changes,
  • Identify the expected and actual result at each stage,
  • Ensure any reasonably skilled user can follow and hit the same issue.

Expected Behavior

On Safari (macOS), sending a chat message in OpenWebUI should render the assistant's reply in the chat bubble, just as it does in Chrome on the same machine.

Actual Behavior

On Safari (macOS 26.3.1), the assistant chat bubble stays empty after submitting a message. The HTTP chat-completion request returns 200 OK and the streamed chunks are visible in the Network tab, so the response is reaching the browser, but it never renders. The same instance works fine in Chrome on the same machine.

The browser console shows that the Socket.IO WebSocket fails:

WebSocket connection to 'ws://192.168.0.3:8282/ws/socket.io/?EIO=4&transport=websocket' failed: WebSocket is closed before the connection is established.

A direct WebSocket upgrade to the same URL via curl returns HTTP/1.1 101 Switching Protocols and the Engine.IO handshake, so the server side is healthy. The failure is in Safari's handling of the Socket.IO handshake, or in an interaction between the OpenWebUI 0.9.2 Socket.IO server and Safari specifically.

Workaround: setting ENABLE_WEBSOCKET_SUPPORT=false on the open-webui service forces Socket.IO to fall back to long polling. Safari then renders responses correctly.

Steps to Reproduce

  1. Run the OpenWebUI main-slim image on a host with Docker. Reported digest: sha256:31b9870915ab83af3c2b9e54559cf09fca33a35822c38547a33e73ed072fb9b1 (version v0.9.2). Host in this report is Synology DSM, but any Docker host should reproduce.
  2. Map host port to container 8080. In this report: 0.0.0.0:8282 -> 8080/tcp. Reach the container directly from a browser, no reverse proxy.
  3. Configure any working OpenAI-compatible backend so chat works in principle. In this report a LiteLLM proxy in front of OpenRouter, but the backend choice is not the cause; LiteLLM is healthy and /v1/chat/completions returns 200 with valid streamed chunks.
  4. Open the OpenWebUI URL in Safari on macOS (reproduced on macOS 26.3.1, Safari 26.3.1).
  5. Sign in. Send a chat message such as hi.
  6. Observe: the user message bubble shows, the assistant bubble appears empty, no content renders. Browser console shows the WebSocket failure quoted above. Network tab shows the chat-completion POST returning 200 and streamed data: ... chunks.
  7. Open the same URL in Chrome on the same machine. Send the same chat message. Observe: the assistant reply renders correctly.
  8. In the OpenWebUI service, set the env var ENABLE_WEBSOCKET_SUPPORT=false. Force redeploy the container so the new env var takes effect (a plain restart did not pick it up in our test).
  9. Hard refresh Safari. Send the same chat message. Observe: the assistant reply now renders correctly via long polling.

Logs & Screenshots

Browser console (Safari 26.3.1)

Viewport argument key "interactive-widget" not recognized and ignored.   (benign, unrelated)
WebSocket connection to 'ws://192.168.0.3:8282/ws/socket.io/?EIO=4&transport=websocket' failed: WebSocket is closed before the connection is established.

Network tab in Safari shows the chat-completion POST returning 200 OK and well-formed data: {...} SSE chunks ending in data: [DONE]. The same chunks render correctly in Chrome.

Server-side WebSocket upgrade is healthy

A direct WebSocket upgrade to the same URL via curl succeeds and returns a valid Engine.IO handshake:

$ curl -i -N \
    -H "Connection: Upgrade" \
    -H "Upgrade: websocket" \
    -H "Sec-WebSocket-Version: 13" \
    -H "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==" \
    "http://192.168.0.3:8282/ws/socket.io/?EIO=4&transport=websocket"

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
date: Tue, 28 Apr 2026 21:30:34 GMT
server: uvicorn

<binary frame>{"sid":"UVtBzQNvVdpQek_AAAAA","upgrades":[],"pingTimeout":20000,"pingInterval":25000,"maxPayload":1000000}

Note "upgrades":[] in the handshake. The request asked for transport=websocket, the server accepted, but it reports no further upgrade options. This is plausibly relevant to Safari's stricter handshake handling.

OpenWebUI container logs

Nothing unusual at startup or during the failing request. The container accepts the chat-completion POST and returns 200. The WebSocket upgrade attempt from Safari does not surface any error in the container logs (no exception, no rejection trace), which is consistent with Safari closing the socket from the client side.

Backend (LiteLLM) is healthy and not implicated

LiteLLM /health returns healthy_count: 3, unhealthy_count: 0 for all configured models. /v1/chat/completions with stream:true returns valid SSE chunks. Backend choice is not the cause; the same Safari instance fails to render even when the backend response is verified valid.

Additional Information

Workaround

Adding ENABLE_WEBSOCKET_SUPPORT=false to the OpenWebUI service forces Socket.IO to long-polling and resolves the issue in Safari. A force redeploy is required, a plain restart did not pick up the new env var in our test.

services:
  open-webui:
    image: ghcr.io/open-webui/open-webui:main-slim
    environment:
      ENABLE_WEBSOCKET_SUPPORT: "false"
    ports:
      - "8282:8080"

Suggested investigation

The Engine.IO handshake response includes "upgrades":[], which is unusual when the request asked for transport=websocket. Worth checking how the Socket.IO server is initialised (async_mode, transports) and whether the engineio and python-socketio versions in the slim image at this digest interact differently with Safari than with Chrome. Chrome on the same machine, same OpenWebUI instance, same backend works fine.

Not exact matches, but Safari plus Socket.IO has been a recurring weak spot:

  • discussion #10847 (Safari SyntaxError: The string did not match the expected pattern.)
  • discussion #4123 (Safari error after first response)
  • issue #8074 (Network Problem 0.5+)
  • issue #8134 (Fresh 0.5.2 WebSocket issues)
  • discussion #13215 (WebSocket disconnects causing UI issues)

Setup detail

  • Host: Synology DSM, Docker via Portainer
  • Backend: LiteLLM proxy in front of OpenRouter (this report exercises it via OpenAI-compatible Connection in OpenWebUI). LiteLLM and OpenRouter both verified healthy.
  • Master key for LiteLLM: a fixed sk-... string, stored in Portainer env vars on the LiteLLM container. Not relevant to the Safari rendering bug.
  • No reverse proxy. No HTTPS. Direct browser access on http://192.168.0.3:8282.
  • LAN access only.
Originally created by @josemodena on GitHub (Apr 28, 2026). Original GitHub issue: https://github.com/open-webui/open-webui/issues/24207 ### Check Existing Issues - [x] I have searched for any existing and/or related issues. - [x] I have searched for any existing and/or related discussions. - [x] I have also searched in the CLOSED issues AND CLOSED discussions and found no related items (your issue might already be addressed on the development branch!). - [x] I am using the latest version of Open WebUI. ### Installation Method Docker ### Open WebUI Version v0.9.2 ### Ollama Version (if applicable) _No response_ ### Operating System macOS 26 ### Browser (if applicable) Safari 26.3.1 (fails); Chrome (works) ### Confirmation - [x] I have read and followed all instructions in `README.md`. - [x] I am using the latest version of **both** Open WebUI and Ollama. - [x] I have included the browser console logs. - [x] I have included the Docker container logs. - [x] I have **provided every relevant configuration, setting, and environment variable used in my setup.** - [x] I have clearly **listed every relevant configuration, custom setting, environment variable, and command-line option that influences my setup** (such as Docker Compose overrides, .env values, browser settings, authentication configurations, etc). - [x] I have documented **step-by-step reproduction instructions that are precise, sequential, and leave nothing to interpretation**. My steps: - Start with the initial platform/version/OS and dependencies used, - Specify exact install/launch/configure commands, - List URLs visited, user input (incl. example values/emails/passwords if needed), - Describe all options and toggles enabled or changed, - Include any files or environmental changes, - Identify the expected and actual result at each stage, - Ensure any reasonably skilled user can follow and hit the same issue. ### Expected Behavior On Safari (macOS), sending a chat message in OpenWebUI should render the assistant's reply in the chat bubble, just as it does in Chrome on the same machine. ### Actual Behavior On Safari (macOS 26.3.1), the assistant chat bubble stays empty after submitting a message. The HTTP chat-completion request returns 200 OK and the streamed chunks are visible in the Network tab, so the response is reaching the browser, but it never renders. The same instance works fine in Chrome on the same machine. The browser console shows that the Socket.IO WebSocket fails: ``` WebSocket connection to 'ws://192.168.0.3:8282/ws/socket.io/?EIO=4&transport=websocket' failed: WebSocket is closed before the connection is established. ``` A direct WebSocket upgrade to the same URL via curl returns `HTTP/1.1 101 Switching Protocols` and the Engine.IO handshake, so the server side is healthy. The failure is in Safari's handling of the Socket.IO handshake, or in an interaction between the OpenWebUI 0.9.2 Socket.IO server and Safari specifically. Workaround: setting `ENABLE_WEBSOCKET_SUPPORT=false` on the `open-webui` service forces Socket.IO to fall back to long polling. Safari then renders responses correctly. ### Steps to Reproduce 1. Run the OpenWebUI `main-slim` image on a host with Docker. Reported digest: `sha256:31b9870915ab83af3c2b9e54559cf09fca33a35822c38547a33e73ed072fb9b1` (version v0.9.2). Host in this report is Synology DSM, but any Docker host should reproduce. 2. Map host port to container 8080. In this report: `0.0.0.0:8282 -> 8080/tcp`. Reach the container directly from a browser, no reverse proxy. 3. Configure any working OpenAI-compatible backend so chat works in principle. In this report a LiteLLM proxy in front of OpenRouter, but the backend choice is not the cause; LiteLLM is healthy and `/v1/chat/completions` returns 200 with valid streamed chunks. 4. Open the OpenWebUI URL in Safari on macOS (reproduced on macOS 26.3.1, Safari 26.3.1). 5. Sign in. Send a chat message such as `hi`. 6. Observe: the user message bubble shows, the assistant bubble appears empty, no content renders. Browser console shows the WebSocket failure quoted above. Network tab shows the chat-completion POST returning 200 and streamed `data: ...` chunks. 7. Open the same URL in Chrome on the same machine. Send the same chat message. Observe: the assistant reply renders correctly. 8. In the OpenWebUI service, set the env var `ENABLE_WEBSOCKET_SUPPORT=false`. Force redeploy the container so the new env var takes effect (a plain restart did not pick it up in our test). 9. Hard refresh Safari. Send the same chat message. Observe: the assistant reply now renders correctly via long polling. ### Logs & Screenshots ## Browser console (Safari 26.3.1) ``` Viewport argument key "interactive-widget" not recognized and ignored. (benign, unrelated) WebSocket connection to 'ws://192.168.0.3:8282/ws/socket.io/?EIO=4&transport=websocket' failed: WebSocket is closed before the connection is established. ``` Network tab in Safari shows the chat-completion POST returning 200 OK and well-formed `data: {...}` SSE chunks ending in `data: [DONE]`. The same chunks render correctly in Chrome. ## Server-side WebSocket upgrade is healthy A direct WebSocket upgrade to the same URL via curl succeeds and returns a valid Engine.IO handshake: ``` $ curl -i -N \ -H "Connection: Upgrade" \ -H "Upgrade: websocket" \ -H "Sec-WebSocket-Version: 13" \ -H "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==" \ "http://192.168.0.3:8282/ws/socket.io/?EIO=4&transport=websocket" HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= date: Tue, 28 Apr 2026 21:30:34 GMT server: uvicorn <binary frame>{"sid":"UVtBzQNvVdpQek_AAAAA","upgrades":[],"pingTimeout":20000,"pingInterval":25000,"maxPayload":1000000} ``` Note `"upgrades":[]` in the handshake. The request asked for `transport=websocket`, the server accepted, but it reports no further upgrade options. This is plausibly relevant to Safari's stricter handshake handling. ## OpenWebUI container logs Nothing unusual at startup or during the failing request. The container accepts the chat-completion POST and returns 200. The WebSocket upgrade attempt from Safari does not surface any error in the container logs (no exception, no rejection trace), which is consistent with Safari closing the socket from the client side. ## Backend (LiteLLM) is healthy and not implicated LiteLLM `/health` returns `healthy_count: 3, unhealthy_count: 0` for all configured models. `/v1/chat/completions` with `stream:true` returns valid SSE chunks. Backend choice is not the cause; the same Safari instance fails to render even when the backend response is verified valid. ### Additional Information ## Workaround Adding `ENABLE_WEBSOCKET_SUPPORT=false` to the OpenWebUI service forces Socket.IO to long-polling and resolves the issue in Safari. A force redeploy is required, a plain restart did not pick up the new env var in our test. ```yaml services: open-webui: image: ghcr.io/open-webui/open-webui:main-slim environment: ENABLE_WEBSOCKET_SUPPORT: "false" ports: - "8282:8080" ``` ## Suggested investigation The Engine.IO handshake response includes `"upgrades":[]`, which is unusual when the request asked for `transport=websocket`. Worth checking how the Socket.IO server is initialised (`async_mode`, `transports`) and whether the `engineio` and `python-socketio` versions in the slim image at this digest interact differently with Safari than with Chrome. Chrome on the same machine, same OpenWebUI instance, same backend works fine. ## Related prior reports Not exact matches, but Safari plus Socket.IO has been a recurring weak spot: - discussion #10847 (Safari `SyntaxError: The string did not match the expected pattern.`) - discussion #4123 (Safari error after first response) - issue #8074 (Network Problem 0.5+) - issue #8134 (Fresh 0.5.2 WebSocket issues) - discussion #13215 (WebSocket disconnects causing UI issues) ## Setup detail - Host: Synology DSM, Docker via Portainer - Backend: LiteLLM proxy in front of OpenRouter (this report exercises it via OpenAI-compatible Connection in OpenWebUI). LiteLLM and OpenRouter both verified healthy. - Master key for LiteLLM: a fixed `sk-...` string, stored in Portainer env vars on the LiteLLM container. Not relevant to the Safari rendering bug. - No reverse proxy. No HTTPS. Direct browser access on `http://192.168.0.3:8282`. - LAN access only.
GiteaMirror added the bug label 2026-05-06 00:22:38 -05:00
Author
Owner

@Classic298 commented on GitHub (May 1, 2026):

Codebase looks fine, nothing Safari-specific stands out. The "upgrades":[] is a red herring: server and client are both pinned to transports: ['websocket'] (no polling at all), so there is nothing to upgrade to. That is also why ENABLE_WEBSOCKET_SUPPORT=false fixes it, it flips both sides to polling.

Before this gets chased as an Open WebUI bug, can you narrow it down?

  1. Does it repro on Safari 18.x / macOS 15, or only on Safari 26 / macOS 26?
  2. Does it repro on Open WebUI 0.8.12 AND latest? Same Safari each time.
    2.1 Same task but with different Safari versions.
  3. From the same Safari, does a plain ws://192.168.0.3:<port> echo server (e.g. websocat) connect, or fail the same way? That isolates WebKit-on-LAN-ws vs. Open WebUI.
  4. Repro in a Private window with all extensions off and Lockdown Mode off?
  5. Does http://localhost:8282 from Safari on the Docker host itself fail the same way?Also useful: the full Safari Web Inspector entry for the failing WS (request and response headers, Sec-WebSocket-Protocol, Sec-WebSocket-Extensions), and the exact macOS build.

Quick one line test on your side: in src/routes/+layout.svelte:122 change ['websocket'] to ['polling', 'websocket'] and see if Safari connects via polling and then upgrades, or connects via polling and fails to upgrade. That tells us if WebKit hates the WS frame itself or just the no-handshake direct-WS path.

<!-- gh-comment-id:4360913959 --> @Classic298 commented on GitHub (May 1, 2026): Codebase looks fine, nothing Safari-specific stands out. The `"upgrades":[]` is a red herring: server and client are both pinned to `transports: ['websocket']` (no polling at all), so there is nothing to upgrade to. That is also why `ENABLE_WEBSOCKET_SUPPORT=false` fixes it, it flips both sides to polling. Before this gets chased as an Open WebUI bug, can you narrow it down? 1. Does it repro on Safari 18.x / macOS 15, or only on Safari 26 / macOS 26? 2. Does it repro on Open WebUI 0.8.12 AND latest? Same Safari each time. 2.1 Same task but with different Safari versions. 3. From the same Safari, does a plain `ws://192.168.0.3:<port>` echo server (e.g. websocat) connect, or fail the same way? That isolates WebKit-on-LAN-ws vs. Open WebUI. 4. Repro in a Private window with all extensions off and Lockdown Mode off? 5. Does `http://localhost:8282` from Safari on the Docker host itself fail the same way?Also useful: the full Safari Web Inspector entry for the failing WS (request and response headers, `Sec-WebSocket-Protocol`, `Sec-WebSocket-Extensions`), and the exact macOS build. Quick one line test on your side: in `src/routes/+layout.svelte:122` change `['websocket']` to `['polling', 'websocket']` and see if Safari connects via polling and then upgrades, or connects via polling and fails to upgrade. That tells us if WebKit hates the WS frame itself or just the no-handshake direct-WS path.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#58896