{"record":{"id":"a3dcb3f0697e69a6","repo":"astral-sh/ruff","slug":"failed-to-fetch-playground-id-response-statu","errorCode":null,"errorMessage":"Failed to fetch playground ${id}: ${response.status}","messagePattern":"Failed to fetch playground (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"playground/ruff/src/Editor/api.ts","lineNumber":16,"sourceCode":"const API_URL = import.meta.env.PROD\n  ? \"https://api.astral-1ad.workers.dev\"\n  : \"http://localhost:8787\";\n\nexport type Playground = {\n  pythonSource: string;\n  settingsSource: string;\n};\n\n/**\n * Fetch a playground by ID.\n */\nexport async function fetchPlayground(id: string): Promise<Playground | null> {\n  const response = await fetch(`${API_URL}/${encodeURIComponent(id)}`);\n  if (!response.ok) {\n    throw new Error(`Failed to fetch playground ${id}: ${response.status}`);\n  }\n  return await response.json();\n}\n\n/**\n * Save a playground and return its ID.\n */\nexport async function savePlayground(playground: Playground): Promise<string> {\n  const response = await fetch(API_URL, {\n    method: \"POST\",\n    body: JSON.stringify(playground),\n  });\n  if (!response.ok) {\n    throw new Error(`Failed to save playground: ${response.status}`);\n  }\n  return await response.text();\n}\n","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/astral-sh/ruff/blob/672bb4edf04c84f8b0753346359daee4057158f2/playground/ruff/src/Editor/api.ts#L1-L34","documentation":"Thrown by the Ruff playground's fetchPlayground when the backend answers a non-2xx HTTP status. Playgrounds are persisted on a Cloudflare worker (https://api.astral-1ad.workers.dev in production, http://localhost:8787 in local dev), so this error means the request reached a server but the server refused or failed it (note: response.json() is only called on success).","triggerScenarios":"GET `${API_URL}/${encodeURIComponent(id)}` returning 404 for an unknown, mistyped, or expired playground ID, or 5xx when the worker itself is failing.","commonSituations":"Opening an old share link whose snippet expired server-side; hand-editing or truncating the ID in a URL; a partially deployed or broken worker.","solutions":["Verify the playground ID in the URL is complete and unmodified","Confirm the worker deployment is healthy (open the API URL directly and check for a sane response) and retry","Ask the sender to re-share the snippet; the stored entry may have expired or never been saved","In local dev, ensure the API worker (localhost:8787) is running before the web dev server calls it"],"exampleFix":"// before\nconst playground = await fetchPlayground(id); // may throw on 404/5xx\n\n// after\ntry {\n  const playground = await fetchPlayground(id);\n} catch (error) {\n  console.error((error as Error).message);\n  // fall back to the default playground content\n}","handlingStrategy":"try-catch","validationCode":"const ID_RE = /^[A-Za-z0-9_-]{4,}$/;\nif (!ID_RE.test(id)) {\n  throw new RangeError(`Invalid playground id: ${id}`);\n}","typeGuard":"function isPlayground(v: unknown): v is Playground {\n  return (\n    typeof v === 'object' && v !== null &&\n    typeof (v as Playground).pythonSource === 'string' &&\n    typeof (v as Playground).settingsSource === 'string'\n  );\n}","tryCatchPattern":"try {\n  const playground = await fetchPlayground(id);\n  if (!playground) return defaults();\n  return playground;\n} catch (error) {\n  console.error(`Could not load shared playground: ${(error as Error).message}`);\n  return defaults();\n}","preventionTips":["Treat playground IDs as opaque; never construct or edit them by hand","Always render a default playground when loading fails instead of crashing the editor","In dev, health-check localhost:8787 before enabling share-button features"],"tags":["network","http","playground","typescript"],"backgroundTag":null,"analyzedSha":"672bb4edf04c84f8b0753346359daee4057158f2","analyzedAt":"2026-08-16T08:54:05.464Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}