{"record":{"id":"1eb062e19c134400","repo":"garrytan/gstack","slug":"blob-too-large-100mb-use-a-different-approach","errorCode":null,"errorMessage":"Blob too large (>100MB). Use a different approach.","messagePattern":"Blob too large \\(>100MB\\)\\. Use a different approach\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"browse/src/write-commands.ts","lineNumber":1203,"sourceCode":"      if (url.startsWith('blob:')) {\n        // Strategy 3: Blob URL -- in-page fetch + base64\n        const dataUrl = await page.evaluate(async (blobUrl) => {\n          try {\n            const resp = await fetch(blobUrl);\n            const blob = await resp.blob();\n            if (blob.size > 100 * 1024 * 1024) return 'ERROR:TOO_LARGE';\n            return new Promise<string>((resolve, reject) => {\n              const reader = new FileReader();\n              reader.onloadend = () => resolve(reader.result as string);\n              reader.onerror = () => reject('Failed to read blob');\n              reader.readAsDataURL(blob);\n            });\n          } catch (err: any) {\n            return `ERROR:EXPIRED:${err?.message || 'unknown'}`;\n          }\n        }, url);\n\n        if (dataUrl === 'ERROR:TOO_LARGE') throw new Error('Blob too large (>100MB). Use a different approach.');\n        if (dataUrl.startsWith('ERROR:EXPIRED')) throw new Error(`Blob URL expired or inaccessible: ${dataUrl.slice('ERROR:EXPIRED:'.length)}`);\n\n        const match = dataUrl.match(/^data:([^;]+);base64,(.+)$/);\n        if (!match) throw new Error('Failed to decode blob data');\n        contentType = match[1];\n        buffer = Buffer.from(match[2], 'base64');\n      } else if (useNavigate) {\n        // Strategy 2: Navigate to URL and capture browser-triggered download.\n        // Handles URLs that trigger file downloads via redirects,\n        // Content-Disposition headers, or anti-bot CDN chains where\n        // page.request.fetch() can't follow the auth/redirect chain.\n        await validateNavigationUrl(url);\n        const downloadPromise = page.waitForEvent('download', { timeout: 60000 });\n        // Use goto with 'commit' wait — the page may redirect to trigger\n        // the download, so 'domcontentloaded' may never fire.\n        page.goto(url, { waitUntil: 'commit', timeout: 30000 }).catch(() => {\n          // Navigation may \"fail\" because the response is a download,\n          // not a page. The download event handles it.","sourceCodeStart":1185,"sourceCodeEnd":1221,"githubUrl":"https://github.com/garrytan/gstack/blob/94993f74012782fd94416dd44b8314f6363a13a4/browse/src/write-commands.ts#L1185-L1221","documentation":"Error \"Blob too large (>100MB). Use a different approach.\" thrown in garrytan/gstack.","triggerScenarios":"Thrown at browse/src/write-commands.ts:1203 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":[],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"94993f74012782fd94416dd44b8314f6363a13a4","analyzedAt":"2026-08-12T04:06:23.140Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}