{"record":{"id":"de04a929aa5cd89f","repo":"windmill-labs/windmill","slug":"recording-exceeded-the-size-limit","errorCode":null,"errorMessage":"Recording exceeded the size limit","messagePattern":"Recording exceeded the size limit","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/recording/rawAppRecordingLoad.ts","lineNumber":619,"sourceCode":"\t\t\t\terror: `This recording is of an unknown kind${named} — it may need a newer Windmill.`\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Fetch a recording from `url`, enforcing the download cap while streaming. */\nexport async function fetchRecording(\n\turl: string,\n\tonProgress?: (loaded: number, total: number) => void\n): Promise<unknown> {\n\tconst res = await fetch(url)\n\tif (!res.ok) throw new Error(`HTTP ${res.status} ${res.statusText}`)\n\tconst total = Number(res.headers.get('content-length')) || 0\n\tif (total > MAX_RECORDING_BYTES) throw new Error(`Recording is too large (${total} bytes)`)\n\tconst reader = res.body?.getReader()\n\tif (!reader) {\n\t\tconst text = await res.text()\n\t\tif (text.length > MAX_RECORDING_BYTES) throw new Error('Recording exceeded the size limit')\n\t\treturn JSON.parse(text)\n\t}\n\tconst chunks: Uint8Array[] = []\n\tlet loaded = 0\n\tfor (;;) {\n\t\tconst { done, value } = await reader.read()\n\t\tif (done) break\n\t\tif (!value) continue\n\t\tchunks.push(value)\n\t\tloaded += value.length\n\t\tif (loaded > MAX_RECORDING_BYTES) {\n\t\t\tawait reader.cancel()\n\t\t\tthrow new Error('Recording exceeded the size limit')\n\t\t}\n\t\tonProgress?.(loaded, total)\n\t}\n\treturn JSON.parse(await new Blob(chunks as BlobPart[]).text())\n}","sourceCodeStart":601,"sourceCodeEnd":637,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/recording/rawAppRecordingLoad.ts#L601-L637","documentation":"When the response has no readable stream (no res.body reader), fetchRecording falls back to reading the whole body as text and enforces the same MAX_RECORDING_BYTES cap on the text length before parsing.","triggerScenarios":"fetchRecording(url) in an environment where res.body is null (older runtimes, some polyfilled fetch) and the downloaded text exceeds the cap.","commonSituations":"Fetching a large recording in a context without streaming response support; very old browser/embedded webview loading the recording page.","solutions":["Reduce the recording size and retry","Use a runtime/browser with streaming response body support (ReadableStream on fetch)","Serve a smaller, pre-trimmed recording file"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (typeof Response !== 'undefined' && new Response().body === null) {\n  warn('Streaming unsupported; size cap applies after full download')\n}","typeGuard":"function supportsStreaming(res: Response): boolean { return !!res.body }","tryCatchPattern":"try { rec = await fetchRecording(url) } catch (e) { if (/size limit/.test(String(e))) notify('Recording too large for this environment'); else throw e }","preventionTips":["Run the recorder page in modern browsers with ReadableStream fetch support","Pre-check file size server-side when serving recordings","Pre-trim recordings before distributing them"],"tags":["recording","size-limit","fetch","compatibility"],"backgroundTag":"payload-size-limit-exceeded","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}