Summary
Opening any Office file (.docx / .xlsx / .pptx) in Firefox on Seafile 13.0.21 with a working OnlyOffice 9.4.0.1 backend results in a blank editor canvas. The exact same file, account, and JWT configuration render the editor correctly in Safari (and Chrome). The failure is an uncaught DOMException raised inside Seafile's own frontend bundle while mounting the editor, before OnlyOffice's iframe ever finishes initializing.
Steps to reproduce
- Deploy Seafile CE 13.0.21 via Docker (
seafileltd/seafile-mc:13.0.21).
- Deploy OnlyOffice DocumentServer 9.4.0.1 (
onlyoffice/documentserver:9.4.0.1) on a separate origin, with JWT_ENABLED=true, JWT_HEADER=Authorization, JWT_IN_BODY=true, and a shared JWT secret.
- Configure
seahub_settings.py exactly per the official integration guide:
ENABLE_ONLYOFFICE = True
ONLYOFFICE_APIJS_URL = 'https://onlyoffice.example.com/web-apps/apps/api/documents/api.js'
ONLYOFFICE_JWT_SECRET = '<shared secret>'
- Open Firefox 151.0.1 on macOS, log in to Seafile, click any
.docx file in a library.
Expected behavior
The OnlyOffice editor mounts inside the file-view page and renders the document — the same behavior observed in Safari and Chrome with an identical configuration.
Observed behavior
- The Seafile file-view toolbar (filename, star, share, info, comments) renders normally.
- The editor area below the toolbar stays blank.
- A single
Uncaught (in promise) DOMException: An invalid or illegal string was specified appears in the Browser Console, raised from commons.<hash>.js via viewFileOnlyoffice.<hash>.js.
- All OnlyOffice assets load (HTTP 200) —
api.js, sdk-all-min.js (3.5 MB), app.css, fonts, locale data. The editor iframe even fetches its subdocument (index.html?_dc=9.4.0-…&lang=en…), but the DOMException in the parent halts the mount.
- DocumentServer's
docservice/out.log shows zero new requests for the failed session, consistent with the parent-page mount aborting before the editor iframe's bootstrap completes.
- Reverting to Safari or Chrome (same session, same JWT, same docx) renders the editor immediately.
Error message
Uncaught (in promise) DOMException: An invalid or illegal string was specified
e https://drive.example.com/media/assets/frontend/static/js/commons.<hash>.js:2
p https://drive.example.com/media/assets/frontend/static/js/commons.<hash>.js:2
s https://drive.example.com/media/assets/frontend/static/js/commons.<hash>.js:2
...
88210 https://drive.example.com/media/assets/frontend/static/js/viewFileOnlyoffice.<hash>.js:1
<anonymous> https://drive.example.com/media/assets/frontend/static/js/viewFileOnlyoffice.<hash>.js:1
commons.<hash>.js:2:1688395
Other (cosmetic) console output observed in the same trace, included for completeness:
Feature Policy: Skipping unsupported feature name "autoplay". api.js:1300:16
Feature Policy: Skipping unsupported feature name "clipboard-write". api.js:1300:16
Failed to load 'https://onlyoffice.example.com/9.4.0-<build>/web-apps/apps/common/Analytics.js'.
A ServiceWorker passed a promise to FetchEvent.respondWith() that rejected with
'TypeError: NetworkError when attempting to fetch resource.'
unreachable code after return statement sdk-all-min.js:21477:2
unreachable code after return statement sdk-all-min.js:55629:54
The Analytics.js NS_ERROR_INTERCEPTION_FAILED is OnlyOffice-side and appears to be a separate, cosmetic issue with their service worker; the editor failure is the DOMException that precedes it.
Editor config delivered by Seahub
Inline var config = {…} block emitted by Seahub on the file-view HTML (JWT signature and user identifiers redacted). The payload is structurally complete and well-formed; the same payload works in Safari/Chrome:
var config = {
"events": {
"onRequestReferenceData": onRequestReferenceData,
"onRequestHistory": onRequestHistory,
"onRequestHistoryData": onRequestHistoryData,
"onRequestHistoryClose": onRequestHistoryClose,
},
"type": window.screen.width < 992 ? 'mobile' : 'desktop',
"document": {
"fileType": "docx",
"key": "<redacted>",
"title": "test.docx",
"url": "https://drive.example.com/seafhttp/files/<token>/test.docx",
"permissions": { "download": true, "edit": true, "fillForms": true, "copy": true, "print": true, "review": true },
"referenceData": { "fileKey": "<redacted JWT>", "instanceId": "https://drive.example.com" }
},
"documentType": "word",
"token": "<redacted JWT>",
"editorConfig": {
"callbackUrl": "https://drive.example.com/onlyoffice/editor-callback/",
"lang": "en",
"mode": "edit",
"customization": { "forcesave": false, "submitForm": false },
"user": { "id": "<redacted>", "name": "<redacted>", "image": "https://drive.example.com/media/avatars/default.png" }
}
};
window.onload = function () {
docEditor = new DocsAPI.DocEditor("placeholder", config);
};
Minor schema drift (not the cause of this bug, but worth flagging): the JS-side editorConfig.user.image field is encoded as editorConfig.user.avatar_url inside the JWT body. Both fields hold the same string, but the JS object and the JWT payload disagree on the key name.
Possible cause
Between Seafile 12.0 and 13.0, the OnlyOffice file-view entry was migrated from React 17.0.2 to React 18.3.1, and from the legacy ReactDom.render(...) API to createRoot(root).render(...):
- // frontend/src/view-file-onlyoffice.js (12.0)
- ReactDom.render(<ViewFileOnlyoffice />, document.getElementById('wrapper'));
+ // frontend/src/view-file-onlyoffice.js (13.0)
+ const root = createRoot(document.getElementById('wrapper'));
+ root.render(<ViewFileOnlyoffice />);
In the same window, frontend/src/components/file-view/file-view.js grew ~55% (6,648 → 10,326 bytes) and now branches on a new documentVendor prop. The most likely culprit is a URL/history-API call inside this component path that runs eagerly under React 18's concurrent root and trips Firefox's stricter argument validation (Firefox is documented to throw InvalidCharacterError for inputs that other engines silently accept).
Seafile 12.0.x (React 17, legacy render API) is reported by the community as still working in Firefox with comparable OnlyOffice versions.
Environment
|
Value |
| Seafile CE |
13.0.21 (seafileltd/seafile-mc:13.0.21) |
| OnlyOffice DocumentServer |
9.4.0.1 (onlyoffice/documentserver:9.4.0.1) |
| Reverse proxy |
Traefik v3, TLS via Cloudflare DNS-01 |
| Browser (broken) |
Firefox 151.0.1 / Gecko build 20260520211922 / macOS 26.5.0 (Apple Silicon, M4 Pro) |
| Browsers (working) |
Safari (macOS 26.5.0); Chrome reported as working by other deployments, not retested by reporter |
| JWT |
matching shared secret on both sides; JWT body and signature decoded and verified |
| Extensions during repro |
uBlock Origin 1.70.0, 1Password, Bitwarden enabled. The DOMException originates entirely in Seafile's own bundles (commons.<hash>.js and viewFileOnlyoffice.<hash>.js), which extension blocking cannot produce. Clean-profile reproduction can be provided on request. |
Summary
Opening any Office file (
.docx/.xlsx/.pptx) in Firefox on Seafile 13.0.21 with a working OnlyOffice 9.4.0.1 backend results in a blank editor canvas. The exact same file, account, and JWT configuration render the editor correctly in Safari (and Chrome). The failure is an uncaughtDOMExceptionraised inside Seafile's own frontend bundle while mounting the editor, before OnlyOffice's iframe ever finishes initializing.Steps to reproduce
seafileltd/seafile-mc:13.0.21).onlyoffice/documentserver:9.4.0.1) on a separate origin, withJWT_ENABLED=true,JWT_HEADER=Authorization,JWT_IN_BODY=true, and a shared JWT secret.seahub_settings.pyexactly per the official integration guide:.docxfile in a library.Expected behavior
The OnlyOffice editor mounts inside the file-view page and renders the document — the same behavior observed in Safari and Chrome with an identical configuration.
Observed behavior
Uncaught (in promise) DOMException: An invalid or illegal string was specifiedappears in the Browser Console, raised fromcommons.<hash>.jsviaviewFileOnlyoffice.<hash>.js.api.js,sdk-all-min.js(3.5 MB),app.css, fonts, locale data. The editor iframe even fetches its subdocument (index.html?_dc=9.4.0-…&lang=en…), but the DOMException in the parent halts the mount.docservice/out.logshows zero new requests for the failed session, consistent with the parent-page mount aborting before the editor iframe's bootstrap completes.Error message
Other (cosmetic) console output observed in the same trace, included for completeness:
The
Analytics.jsNS_ERROR_INTERCEPTION_FAILEDis OnlyOffice-side and appears to be a separate, cosmetic issue with their service worker; the editor failure is the DOMException that precedes it.Editor config delivered by Seahub
Inline
var config = {…}block emitted by Seahub on the file-view HTML (JWT signature and user identifiers redacted). The payload is structurally complete and well-formed; the same payload works in Safari/Chrome:Minor schema drift (not the cause of this bug, but worth flagging): the JS-side
editorConfig.user.imagefield is encoded aseditorConfig.user.avatar_urlinside the JWT body. Both fields hold the same string, but the JS object and the JWT payload disagree on the key name.Possible cause
Between Seafile 12.0 and 13.0, the OnlyOffice file-view entry was migrated from React 17.0.2 to React 18.3.1, and from the legacy
ReactDom.render(...)API tocreateRoot(root).render(...):In the same window,
frontend/src/components/file-view/file-view.jsgrew ~55% (6,648 → 10,326 bytes) and now branches on a newdocumentVendorprop. The most likely culprit is aURL/history-API call inside this component path that runs eagerly under React 18's concurrent root and trips Firefox's stricter argument validation (Firefox is documented to throwInvalidCharacterErrorfor inputs that other engines silently accept).Seafile 12.0.x (React 17, legacy render API) is reported by the community as still working in Firefox with comparable OnlyOffice versions.
Environment
13.0.21(seafileltd/seafile-mc:13.0.21)9.4.0.1(onlyoffice/documentserver:9.4.0.1)20260520211922/ macOS 26.5.0 (Apple Silicon, M4 Pro)commons.<hash>.jsandviewFileOnlyoffice.<hash>.js), which extension blocking cannot produce. Clean-profile reproduction can be provided on request.