Office editor shows "Download failed" on member instances: OnlyOffice realtime channel does not complete through the login-gated proxy #32

Closed
opened 2026-06-18 06:00:24 +00:00 by mik-tf · 2 comments
Owner

On a member instance, opening a document in the desktop Office app loads the OnlyOffice editor UI but then fails with "Download failed", so no document ever opens. I traced this end to end on a live member.

The document fetch and save path is now fine. OnlyOffice's engine successfully downloads and converts a real document from the member's https FQDN. The connector was just changed from the member's mycelium [ipv6]:9997 address (which OnlyOffice's Node URL parser rejects with ERR_INVALID_URL, so it could never fetch or post the save callback) to https://, and the served editor config plus its signed token both validate against the engine secret.

The remaining blocker is the browser to engine realtime channel. OnlyOffice opens a socket.io connection (polling then websocket upgrade) to the Document Server through the member's hero_proxy and the public gateway, and that connection does not complete for the logged-in member, so the engine never receives the open command (no server side document download is ever attempted in the engine logs) and the editor reports "Download failed". The OnlyOffice static assets (api.js) do load for the authenticated user, so it is specifically the realtime co-authoring channel that fails, not asset serving.

hero_proxy has a websocket upgrade tunnel, but it only runs for http/https upstream routes and the OnlyOffice asset and realtime path sits behind the always-on login floor, so the likely area is how the authenticated socket.io polling and the websocket upgrade are routed and tunneled through that floor, and whether the gateway forwards the upgrade. Engine, connector, JWT, and the per context document store are all confirmed working.

Part of #31

On a member instance, opening a document in the desktop Office app loads the OnlyOffice editor UI but then fails with "Download failed", so no document ever opens. I traced this end to end on a live member. The document fetch and save path is now fine. OnlyOffice's engine successfully downloads and converts a real document from the member's https FQDN. The connector was just changed from the member's mycelium [ipv6]:9997 address (which OnlyOffice's Node URL parser rejects with ERR_INVALID_URL, so it could never fetch or post the save callback) to https://<member-fqdn>, and the served editor config plus its signed token both validate against the engine secret. The remaining blocker is the browser to engine realtime channel. OnlyOffice opens a socket.io connection (polling then websocket upgrade) to the Document Server through the member's hero_proxy and the public gateway, and that connection does not complete for the logged-in member, so the engine never receives the open command (no server side document download is ever attempted in the engine logs) and the editor reports "Download failed". The OnlyOffice static assets (api.js) do load for the authenticated user, so it is specifically the realtime co-authoring channel that fails, not asset serving. hero_proxy has a websocket upgrade tunnel, but it only runs for http/https upstream routes and the OnlyOffice asset and realtime path sits behind the always-on login floor, so the likely area is how the authenticated socket.io polling and the websocket upgrade are routed and tunneled through that floor, and whether the gateway forwards the upgrade. Engine, connector, JWT, and the per context document store are all confirmed working. Part of https://forge.ourworld.tf/lhumina_code/hero_office/issues/31
Member
Fixed in https://forge.ourworld.tf/lhumina_code/hero_router/commit/7e42b8a44289cbc17d01d673b3a763993b2d302d ![image](/attachments/72e54405-9dd8-4f8c-aea8-519d7f9bdfe5) ![image](/attachments/2ea11fcc-a3d1-408a-a4c8-62a3ba6cf500) ![image](/attachments/d7833062-d133-498b-a1cb-fd87c8d1c6d6)
Author
Owner

Fixed and verified live: a member can now open and edit a document end to end, including the live collaboration socket.

Root cause: OnlyOffice builds its own browser-facing asset URLs (the editor code Editor.bin and the cache resources) from the X-Forwarded-Host header. hero_office_admin was deriving that header from the inbound Host header, but after the request passes through hero_proxy and hero_router the Host is the internal router address (127.0.0.1:9988). So the engine told the browser to load the editor code from https://127.0.0.1:9988/ which a public browser cannot reach. The editor failed loading its own code before it could open the document socket, which is why the browser never made a socket request and the engine never logged a download attempt. The public gateway and the login gate were both ruled out as causes.

Fix: hero_office_admin now sources the public host from CONNECTOR_EXTERNAL_URL (the member's public address, already used to build the document and callback URLs) and uses it for X-Forwarded-Host on both the HTTP and WebSocket proxy paths. Shipped on the hero_office integration branch (703a9db). It reaches existing members on the next update and new instances automatically, since the deployer already seeds CONNECTOR_EXTERNAL_URL at install.

Fixed and verified live: a member can now open and edit a document end to end, including the live collaboration socket. Root cause: OnlyOffice builds its own browser-facing asset URLs (the editor code Editor.bin and the cache resources) from the X-Forwarded-Host header. hero_office_admin was deriving that header from the inbound Host header, but after the request passes through hero_proxy and hero_router the Host is the internal router address (127.0.0.1:9988). So the engine told the browser to load the editor code from https://127.0.0.1:9988/ which a public browser cannot reach. The editor failed loading its own code before it could open the document socket, which is why the browser never made a socket request and the engine never logged a download attempt. The public gateway and the login gate were both ruled out as causes. Fix: hero_office_admin now sources the public host from CONNECTOR_EXTERNAL_URL (the member's public address, already used to build the document and callback URLs) and uses it for X-Forwarded-Host on both the HTTP and WebSocket proxy paths. Shipped on the hero_office integration branch (703a9db). It reaches existing members on the next update and new instances automatically, since the deployer already seeds CONNECTOR_EXTERNAL_URL at install.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_office#32
No description provided.