{"record":{"id":"70398bcb6206c14c","repo":"BabylonJS/Babylon.js","slug":"unable-to-save-your-entityname-content","errorCode":null,"errorMessage":"Unable to save your ${entityName ?? \"content\"}: ${e}","messagePattern":"Unable to save your (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/inspector-v2/src/misc/snippetUtils.ts","lineNumber":82,"sourceCode":"        name: \"\",\r\n        description: \"\",\r\n        tags: \"\",\r\n    };\r\n\r\n    const headers = new Headers();\r\n    headers.append(\"Content-Type\", \"application/json\");\r\n\r\n    let response: Response;\r\n    try {\r\n        response = await fetch(snippetUrl + (currentSnippetId ? \"/\" + currentSnippetId : \"\"), {\r\n            method: \"POST\",\r\n            headers,\r\n            body: JSON.stringify(dataToSend),\r\n        });\r\n    } catch (e) {\r\n        const errorMsg = `Unable to save 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 save your ${entityName ?? \"content\"}`;\r\n        alert(errorMsg);\r\n        throw new Error(errorMsg);\r\n    }\r\n\r\n    const snippet = await response.json();\r\n    const oldSnippetId = currentSnippetId || \"_BLANK\";\r\n    let newSnippetId = snippet.id;\r\n    if (snippet.version && snippet.version !== \"0\") {\r\n        newSnippetId += \"#\" + snippet.version;\r\n    }\r\n\r\n    // Copy to clipboard when available.\r\n    if (navigator.clipboard) {\r\n        await navigator.clipboard.writeText(newSnippetId);\r","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/inspector-v2/src/misc/snippetUtils.ts#L64-L100","documentation":"SaveToSnippetServer wraps the fetch() POST to the snippet server in a try/catch; if the network request itself throws (never reaches an HTTP response), it builds this message including the underlying error text, calls alert(), and rethrows with the original error as `cause`. It exists to tell the user which entity type (e.g. 'particle system') failed to save while preserving the root cause (network failure, CORS, invalid URL, server unreachable).","triggerScenarios":"Calling SaveToSnippetServer when fetch() rejects: snippet server host unreachable or offline, invalid/incorrect snippetUrl (bad protocol, typo, mixed HTTP/HTTPS content blocking), CORS rejection, browser offline, DNS failure, or the request aborted before a Response is produced.","commonSituations":"Running the inspector against a locally started snippet server that is not running yet; a snippetUrl with a trailing typo or wrong port; CORS not enabled on a self-hosted snippet server; corporate proxy/firewall blocking the request; testing in an environment without network access.","solutions":["Verify the snippet server is running and that config.snippetUrl points at the correct host/port/protocol (https on https pages).","Open the browser console/network tab and inspect `e` (the Error.cause) to see if it is CORS, DNS, or a connection refusal, and fix that root cause.","If self-hosting the snippet server, enable CORS headers for the page origin.","Add retry logic or a health check against snippetUrl before invoking save.","If you only need local persistence, bypass the server and store the content via localStorage instead."],"exampleFix":"// before: fails silently into alert when server is down\nawait SaveToSnippetServer({ snippetUrl: \"http://localhost:1338\", content, payloadKey: \"particleSystem\" });\n\n// after: probe server first and fall back\nasync function saveSnippet(config) {\n  try {\n    await fetch(config.snippetUrl, { method: \"HEAD\" });\n  } catch {\n    localStorage.setItem(\"snippet-backup\", config.content);\n    throw new Error(\"Snippet server unreachable; content backed up locally\");\n  }\n  return SaveToSnippetServer(config);\n}","handlingStrategy":"try-catch","validationCode":"async function assertSnippetServerReady(snippetUrl) {\n  const u = new URL(snippetUrl);\n  if (window.location.protocol === \"https:\" && u.protocol !== \"https:\") {\n    throw new Error(\"Mixed content: snippet server must use https\");\n  }\n  await fetch(snippetUrl, { method: \"HEAD\" });\n}","typeGuard":null,"tryCatchPattern":"try {\n  const result = await SaveToSnippetServer(config);\n} catch (e) {\n  console.error(\"Snippet save failed:\", e.cause ?? e);\n  // e.cause holds the original fetch error (CORS, DNS, offline)\n  localStorage.setItem(\"snippet-backup:\" + config.payloadKey, config.content);\n}","preventionTips":["HEAD-check the snippet server on inspector startup and show a status indicator.","Keep snippetUrl in one config source and validate protocol against the page origin.","Enable CORS on any self-hosted snippet server.","Back up content to localStorage on save failure so work is never lost."],"tags":["network","fetch","snippet-server","browser"],"backgroundTag":"fetch-network-error","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}