{"record":{"id":"e51d507a460697d3","repo":"jackwener/OpenCLI","slug":"file-too-large-e51d50","errorCode":"FILE_TOO_LARGE","errorMessage":"FILE_TOO_LARGE","messagePattern":"FILE_TOO_LARGE","errorType":"error_code","errorClass":"CliError","httpStatus":null,"severity":"error","filePath":"clis/yollomi/upload.js","lineNumber":43,"sourceCode":"    strategy: Strategy.COOKIE,\n    args: [\n        { name: 'file', positional: true, required: true, help: 'Local file path to upload' },\n    ],\n    columns: ['status', 'file', 'size', 'url'],\n    func: async (page, kwargs) => {\n        const filePath = path.resolve(kwargs.file);\n        if (!fs.existsSync(filePath))\n            throw new CliError('FILE_NOT_FOUND', `File not found: ${filePath}`, 'Provide a valid file path');\n        const ext = path.extname(filePath).toLowerCase();\n        const mime = MIME_MAP[ext];\n        if (!mime)\n            throw new CliError('INVALID_TYPE', `Unsupported file type: ${ext}`, 'Supported: jpg, png, gif, webp, mp4, mov');\n        const data = fs.readFileSync(filePath);\n        // Note: base64 encoding inflates size ~33%. Video cap is conservative to avoid\n        // OOM when the base64 string is injected into the browser JS engine via page.evaluate().\n        const maxSize = mime.startsWith('video/') ? 20 * 1024 * 1024 : 10 * 1024 * 1024;\n        if (data.length > maxSize)\n            throw new CliError('FILE_TOO_LARGE', `File too large: ${fmtBytes(data.length)}`, `Max ${mime.startsWith('video/') ? '20MB' : '10MB'} (upload larger videos from a URL)`);\n        const b64 = data.toString('base64');\n        const fileName = path.basename(filePath);\n        log.status(`Uploading ${fileName} (${fmtBytes(data.length)})...`);\n        await ensureOnYollomi(page);\n        const result = await page.evaluate(`\n      (async () => {\n        try {\n          const raw = atob(${JSON.stringify(b64)});\n          const arr = new Uint8Array(raw.length);\n          for (let i = 0; i < raw.length; i++) arr[i] = raw.charCodeAt(i);\n          const file = new File([arr], ${JSON.stringify(fileName)}, { type: ${JSON.stringify(mime)} });\n          const fd = new FormData();\n          fd.append('file', file);\n          const res = await fetch('/api/upload', { method: 'POST', body: fd, credentials: 'include' });\n          const json = await res.json();\n          return { ok: res.ok, status: res.status, data: json };\n        } catch (err) {\n          return { ok: false, status: 0, data: { error: err.message } };","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/yollomi/upload.js#L25-L61","documentation":"FILE_TOO_LARGE is thrown when the file read into memory exceeds the size cap for its MIME class: 20MB for video, 10MB for everything else. The caps exist because the file is base64-encoded (~33% larger) and injected into the browser JS engine via page.evaluate(), so oversized payloads risk OOM crashes of the Chrome tab.","triggerScenarios":"Calling the upload command with a file whose byte length (fs.readFileSync result) exceeds 10MB for images or 20MB for videos — e.g. a 12MB png screenshot or a 25MB mp4 clip.","commonSituations":"Uploading raw camera 4K video clips, high-resolution PNG screenshots, uncompressed scans, or GIF exports from animation tools; also hitting the cap after the file passed the type check because size was never considered.","solutions":["Compress or downscale the file (e.g. export the image as jpg quality ~80, or re-encode video at a lower bitrate)","For videos over 20MB, use the documented alternative: upload from a URL instead of embedding the file","Check the size first with `ls -lh` or `stat -c %s` and split/trim media (e.g. trim video length)","If the file is a video, remember the cap is 20MB; images cap at 10MB — verify you are not misclassifying"],"exampleFix":"// before\nyollomi upload ./screen-recording.mov  // 40MB\n// throws FILE_TOO_LARGE\n// after\nffmpeg -i screen-recording.mov -b:v 1M -fs 18M screen-recording-small.mov\nyollomi upload ./screen-recording-small.mov","handlingStrategy":"validation","validationCode":"const stat = fs.statSync(file);\nconst isVideo = ['.mp4','.mov'].includes(path.extname(file).toLowerCase());\nconst max = isVideo ? 20*1024*1024 : 10*1024*1024;\nif (stat.size > max) throw new Error(`${file} is ${stat.size} bytes; max ${max}`);","typeGuard":"function withinSizeLimit(file) {\n  const video = ['.mp4','.mov'].includes(path.extname(file).toLowerCase());\n  const max = video ? 20*1024*1024 : 10*1024*1024;\n  return fs.existsSync(file) && fs.statSync(file).size <= max;\n}","tryCatchPattern":"try {\n  await upload(file);\n} catch (e) {\n  if (e.code === 'FILE_TOO_LARGE') console.error('Compress or upload from a URL instead');\n  else throw e;\n}","preventionTips":["Pre-check file sizes with fs.statSync before invoking upload","Compress images to jpg and videos with ffmpeg as a pipeline step","Route oversized videos through the URL-upload path instead of local files"],"tags":["cli","file-upload","file-size","limit-exceeded"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}