Troubleshooting
When a serverless app can’t render, the Crowdin host replaces it with a diagnostic panel. Each panel maps to a specific failure:
| Panel | What happened |
|---|---|
| This app has no bundle yet | The app has no JavaScript bundle to run - nothing was published and no dev server is linked |
| We couldn’t load the app | The bundle URL failed to load |
| The app is taking too long to load | The bundle didn’t respond within a few seconds |
| The app didn’t start | The bundle loaded but never registered the expected module |
This app has no bundle yet
Section titled “This app has no bundle yet”Run publish to upload a bundle, or dev and accept the switch to the external bundle mode so Crowdin loads the app from your machine.
We couldn’t load the app
Section titled “We couldn’t load the app”When the bundle URL points at localhost, check that the dev server is actually running on that port. Two browser-specific traps:
- Chrome blocks requests to local addresses unless the page is allowed local network access - check the permission prompt or site settings.
- Safari refuses plain-HTTP localhost requests from an HTTPS page, and the CLI dev server is HTTP-only - publish the bundle instead, or develop in another browser (a local HTTPS reverse proxy in front of the dev server also works).
For a published bundle, reload the page; if it persists, the uploaded bundle is broken - re-run publish.
The app is taking too long to load
Section titled “The app is taking too long to load”The bundle URL is reachable but slow to respond. With a dev server, check it is running and reachable on that address (the first compile after startup can also take a moment - reload once it settles). For a published bundle, check your network connection and reload the page.
The app didn’t start
Section titled “The app didn’t start”The bundle executed, but the host waited and no module matching context.app.type and key was registered. Typical causes:
- Registration ran too late.
prepare*calls must run synchronously at the top level of the bundle - not inside an async callback, a dynamic import, or an event handler. - Key mismatch. With several modules of one type in the manifest, each registration must pass its manifest
key:prepareProjectMenu({ … }, "my-key"). - Module type not registered at all. Every module type declared in the manifest must have a matching
prepare*call in the bundle - one bundle serves them all.
The browser console shows what the SDK dispatcher resolved ([apps-sdk] no module registered for …).
Opening the app directly in a browser
Section titled “Opening the app directly in a browser”The bundle only runs inside the Crowdin host - opened directly (e.g. http://localhost:8080/app.js or your external URL), the SDK has no host bridge to talk to and throws. To see the app, open it inside Crowdin: preview deep-links to the right page.
Changes don’t show up
Section titled “Changes don’t show up”- Translation catalogs are compiled once when
devstarts - restart the dev server after editing.pofiles. - The local
manifest.jsonand Crowdin’s copy can drift -manifest statusshows the diff (and exits with code 1),manifest push/manifest pullresolve it.
The console shows Content Security Policy violations
Section titled “The console shows Content Security Policy violations”The app iframe runs under a strict CSP. What it allows and forbids:
- Allowed:
fetch/XHR/WebSocket requests to any HTTPS host (plus localhost during development) - calling third-party APIs directly is fine; images, media, and fonts fromhttps:,data:, andblob:URLs. - Forbidden: Web Workers (
worker-src 'none'- breaks libraries that spawn workers, such as code editors or PDF renderers), nested iframes and embeds (frame-src/child-src 'none'), native form submissions (form-action 'none'), and scripts from anywhere but the app’s bundle.
A library that fails only inside Crowdin most likely hits one of these - the console’s CSP violation report names the blocked directive.
API calls fail
Section titled “API calls fail”- Every REST call must be covered by the
scopesdeclared in the manifest - calls outside them are rejected, and an emptyscopesarray means no API access at all. Note that:writedoes not imply read access. FormDatabodies and GraphQL are not supported by the host bridge - see the API limitations.