{"record":{"id":"97e6ffc46e4e0ef8","repo":"BabylonJS/Babylon.js","slug":"unable-to-load-your-entityname-content","errorCode":null,"errorMessage":"Unable to load your ${entityName ?? \"content\"}: ${e}","messagePattern":"Unable to load your (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/inspector-v2/src/misc/snippetUtils.ts","lineNumber":143,"sourceCode":"    /** Optional friendly name for the entity type (used in alerts). */\r\n    entityName?: string;\r\n};\r\n\r\n/**\r\n * Load content from the snippet server.\r\n * @param config Configuration for the load operation.\r\n * @returns Promise resolving to the parsed response object.\r\n */\r\nexport async function LoadFromSnippetServer(config: LoadFromSnippetConfig): Promise<any> {\r\n    const { snippetUrl, snippetId, entityName } = config;\r\n\r\n    let response: Response;\r\n    try {\r\n        response = await fetch(snippetUrl + \"/\" + snippetId.replace(/#/g, \"/\"));\r\n    } catch (e) {\r\n        const errorMsg = `Unable to load your ${entityName ?? \"content\"}: ${e}`;\r\n        alert(errorMsg);\r\n        throw new Error(errorMsg, { cause: e });\r\n    }\r\n\r\n    if (!response.ok) {\r\n        const errorMsg = `Unable to load your ${entityName ?? \"content\"}`;\r\n        alert(errorMsg);\r\n        throw new Error(errorMsg);\r\n    }\r\n\r\n    return await response.json();\r\n}\r\n\r\n/**\r\n * Prompt the user for a snippet ID.\r\n * @param message The prompt message.\r\n * @returns The trimmed snippet ID, or null if cancelled/empty.\r\n */\r\nexport function PromptForSnippetId(message: string = \"Please enter the snippet ID to use\"): string | null {\r\n    const requestedSnippetId = window.prompt(message);\r","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/inspector-v2/src/misc/snippetUtils.ts#L125-L161","documentation":"LoadFromSnippetServer wraps its GET fetch(snippetUrl + \"/\" + snippetId) in try/catch; if the request throws before a Response is produced, it alerts and throws this message with the original error as `cause`. It distinguishes network-level load failures (server unreachable, CORS, bad URL) from server-rejected loads.","triggerScenarios":"Calling LoadFromSnippetServer when fetch() rejects: snippet server offline or unreachable, snippetUrl misconfigured (wrong host/protocol), CORS block, mixed-content blocking (https page fetching http snippet server), offline browser, or malformed snippetId producing an unrequestable URL.","commonSituations":"Loading a shared snippet while the public snippet server is down; a typo'd snippetUrl in tool configuration; opening an http snippet server from an https-hosted playground (mixed content); VPN/proxy blocking the request; snippet ID containing characters that break the URL.","solutions":["Verify the snippet server is reachable at snippetUrl (curl or browser GET) and the URL scheme matches the page (https vs http).","Inspect the thrown Error.cause in the console to identify CORS vs DNS vs connection-refused, and fix accordingly.","Validate the snippetId format before calling (non-empty, no illegal URL characters); '#' is converted to '/', other characters are not sanitized.","Enable CORS on a self-hosted snippet server for the page's origin.","Implement a retry with backoff for transient network failures, or prompt the user for a corrected snippet ID."],"exampleFix":"// before\nconst data = await LoadFromSnippetServer({ snippetUrl: cfg.url, snippetId: id });\n\n// after: validate and retry\nif (!id || !/^[A-Za-z0-9#._-]+$/.test(id)) throw new Error(\"Invalid snippet ID: \" + id);\nlet data;\nfor (let attempt = 0; attempt < 3; attempt++) {\n  try { data = await LoadFromSnippetServer({ snippetUrl: cfg.url, snippetId: id }); break; }\n  catch (e) { if (attempt === 2) throw e; await new Promise(r => setTimeout(r, 500 * (attempt + 1))); }\n}","handlingStrategy":"validation","validationCode":"function canAttemptLoad(config) {\n  return Boolean(\n    config &&\n    /^https?:\\/\\//.test(config.snippetUrl || \"\") &&\n    typeof config.snippetId === \"string\" &&\n    config.snippetId.trim().length > 0 &&\n    /^[A-Za-z0-9#._-]+$/.test(config.snippetId.trim())\n  );\n}","typeGuard":"function isLoadConfig(c) {\n  return typeof c === \"object\" && c !== null &&\n    typeof (c as any).snippetUrl === \"string\" && /^https?:\\/\\//.test((c as any).snippetUrl) &&\n    typeof (c as any).snippetId === \"string\" && (c as any).snippetId.length > 0;\n}","tryCatchPattern":"try {\n  const data = await LoadFromSnippetServer(config);\n} catch (e) {\n  const cause = (e as any).cause;\n  if (cause instanceof TypeError) {\n    console.error(\"Network/CORS failure loading snippet:\", cause.message);\n  } else {\n    console.error(\"Snippet load failed:\", cause ?? e);\n  }\n}","preventionTips":["Always trim and sanitize user-provided snippet IDs before loading.","Ensure the page protocol matches the snippet server protocol (avoid mixed content).","Retry transient network failures with exponential backoff.","Surface a clear 'server unreachable' state instead of relying on the alert()."],"tags":["network","fetch","snippet-server","cors"],"backgroundTag":"fetch-network-error","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}