OrchardCMS/OrchardCore · error · Error
Failed to load
Error message
Failed to load ${CONFIG_URL}: ${response.status} ${response.statusText} What it means
The standalone media gallery boots by fetching config.json (CONFIG_URL) relative to the script location with cache: no-store. If the HTTP response is not ok, it throws an Error containing the status code and status text. This is a bootstrap guard: without config the Vue app cannot know the Orchard base URL or runtime options.
Solutions
- Ensure config.json is deployed next to the standalone bundle at the URL the page fetches.
- Check the browser Network tab for the actual failing URL and status; fix the hosting path or permissions.
- Verify static files (including .json) are served by the host (web server config, SPA fallback rules).
- Handle the rejection in bootstrap code and show a user-friendly message pointing at the missing config.
Example fix
// before
throw new Error(`Failed to load ${CONFIG_URL}: ${response.status} ${response.statusText}`);
// after
if (!response.ok) {
console.error(`config.json fetch failed: ${response.status}; ensure config.json is deployed next to the bundle`);
return fallbackConfig;
} Defensive patterns
Strategy: fallback
Validate before calling
// Pre-flight check the config endpoint
const res = await fetch('config.json', { cache: 'no-store' });
if (!res.ok) console.warn(`config.json unavailable: ${res.status}; check deployment`); Try / catch
try { const src = await loadConfigSource(); }
catch (err) {
document.body.innerHTML = 'Media gallery failed to load configuration. Ensure config.json is deployed.';
throw err;
} Prevention
- Always deploy config.json alongside the standalone bundle.
- Add config.json to deployment manifests and CI artifacts.
- Verify the page's base path so relative fetches resolve correctly.
- Check server auth rules that may block anonymous static JSON requests.
When it happens
Trigger: Opening the standalone media gallery page when config.json is absent from the served location, returns 404/500, or the static file middleware/server fails to serve it.
Common situations: Deploying only the JS bundle without the accompanying config.json; wrong base path in hosting (config.json resolved relative to the app root); server returning 401/403 due to auth on static files; CDN misconfiguration.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- is missing the required "orchardBaseUrl" field.
- nestedSortable: Please check that the listType option is…
- A feature is missing a mandatory 'Id' property in the Module
- File path must be a non-empty string.
- Top level JSON element must be an object. Instead
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/4bb62b7d5b9caeba.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore.Modules/OrchardCore.Media/Assets/media-gallery/src/standalone.ts:34
setRuntimeConfig,
type IStandaloneConfigSource,
type IMediaRuntimeConfig,
} from "./services/RuntimeConfig";
/**
* Entry point for the **standalone** media gallery — the app hosted on its own origin against a
* remote OrchardCore tenant. Unlike the embedded entry (main.ts), there is no Razor host to inject
* `<media-gallery>` attributes: config comes from a fetched `config.json`, and the App is rendered
* with an already-resolved two-origin runtime config. Auth is bearer + interactive (handled inside
* App.vue from the injected config).
*/
const CONFIG_URL = "config.json";
async function loadConfigSource(): Promise<IStandaloneConfigSource> {
const response = await fetch(CONFIG_URL, { cache: "no-store" });
if (!response.ok) {
throw new Error(`Failed to load ${CONFIG_URL}: ${response.status} ${response.statusText}`);
}
const source = (await response.json()) as IStandaloneConfigSource;
if (!source.orchardBaseUrl) {
throw new Error(`${CONFIG_URL} is missing the required "orchardBaseUrl" field.`);
}
return source;
}
/** Load the media gallery's UI labels from the remote Orchard tenant (the same "media-gallery" JS
* localizations the embedded admin page renders, for the server's resolved culture). The endpoint is
* anonymous, so this runs before authentication. Falls back to an empty set on failure. */
async function loadTranslations(apiBaseUrl: string): Promise<string> {
try {
// Default fetch caching: the endpoint serves Cache-Control/ETag, so repeat loads hit the
// browser cache or revalidate to a 304 instead of re-downloading the label set every boot.
const base = apiBaseUrl.endsWith("/") ? apiBaseUrl : `${apiBaseUrl}/`;
const response = await fetch(`${base}api/media/localizations`);
if (response.ok) {View on GitHub (pinned to 4306c0717f)