{"record":{"id":"4bb62b7d5b9caeba","repo":"OrchardCMS/OrchardCore","slug":"failed-to-load-config-url-response-status-response","errorCode":null,"errorMessage":"Failed to load ${CONFIG_URL}: ${response.status} ${response.statusText}","messagePattern":"Failed to load (.+?): (.+?) (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/OrchardCore.Modules/OrchardCore.Media/Assets/media-gallery/src/standalone.ts","lineNumber":34,"sourceCode":"  setRuntimeConfig,\n  type IStandaloneConfigSource,\n  type IMediaRuntimeConfig,\n} from \"./services/RuntimeConfig\";\n\n/**\n * Entry point for the **standalone** media gallery — the app hosted on its own origin against a\n * remote OrchardCore tenant. Unlike the embedded entry (main.ts), there is no Razor host to inject\n * `<media-gallery>` attributes: config comes from a fetched `config.json`, and the App is rendered\n * with an already-resolved two-origin runtime config. Auth is bearer + interactive (handled inside\n * App.vue from the injected config).\n */\n\nconst CONFIG_URL = \"config.json\";\n\nasync function loadConfigSource(): Promise<IStandaloneConfigSource> {\n  const response = await fetch(CONFIG_URL, { cache: \"no-store\" });\n  if (!response.ok) {\n    throw new Error(`Failed to load ${CONFIG_URL}: ${response.status} ${response.statusText}`);\n  }\n  const source = (await response.json()) as IStandaloneConfigSource;\n  if (!source.orchardBaseUrl) {\n    throw new Error(`${CONFIG_URL} is missing the required \"orchardBaseUrl\" field.`);\n  }\n  return source;\n}\n\n/** Load the media gallery's UI labels from the remote Orchard tenant (the same \"media-gallery\" JS\n * localizations the embedded admin page renders, for the server's resolved culture). The endpoint is\n * anonymous, so this runs before authentication. Falls back to an empty set on failure. */\nasync function loadTranslations(apiBaseUrl: string): Promise<string> {\n  try {\n    // Default fetch caching: the endpoint serves Cache-Control/ETag, so repeat loads hit the\n    // browser cache or revalidate to a 304 instead of re-downloading the label set every boot.\n    const base = apiBaseUrl.endsWith(\"/\") ? apiBaseUrl : `${apiBaseUrl}/`;\n    const response = await fetch(`${base}api/media/localizations`);\n    if (response.ok) {","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore.Modules/OrchardCore.Media/Assets/media-gallery/src/standalone.ts#L16-L52","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nthrow new Error(`Failed to load ${CONFIG_URL}: ${response.status} ${response.statusText}`);\n// after\nif (!response.ok) {\n  console.error(`config.json fetch failed: ${response.status}; ensure config.json is deployed next to the bundle`);\n  return fallbackConfig;\n}","handlingStrategy":"fallback","validationCode":"// Pre-flight check the config endpoint\nconst res = await fetch('config.json', { cache: 'no-store' });\nif (!res.ok) console.warn(`config.json unavailable: ${res.status}; check deployment`);","typeGuard":null,"tryCatchPattern":"try { const src = await loadConfigSource(); }\ncatch (err) {\n  document.body.innerHTML = 'Media gallery failed to load configuration. Ensure config.json is deployed.';\n  throw err;\n}","preventionTips":["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."],"tags":["network","javascript","fetch","configuration"],"backgroundTag":"http-error-response","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}