{"record":{"id":"362e85baa55e7cfa","repo":"jackwener/OpenCLI","slug":"invalid-type","errorCode":"INVALID_TYPE","errorMessage":"INVALID_TYPE","messagePattern":"INVALID_TYPE","errorType":"error_code","errorClass":"CliError","httpStatus":null,"severity":"error","filePath":"clis/yollomi/upload.js","lineNumber":37,"sourceCode":"cli({\n    site: 'yollomi',\n    name: 'upload',\n    access: 'write',\n    description: 'Upload an image or video to Yollomi (returns URL for other commands)',\n    domain: YOLLOMI_DOMAIN,\n    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();","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/yollomi/upload.js#L19-L55","documentation":"INVALID_TYPE is thrown by the yollomi upload command when the file's extension is not present in the MIME_MAP lookup table. The library only supports a fixed set of media types (jpg, png, gif, webp, mp4, mov) because those are what the yollomi.com upload endpoint and its browser-bridge injection can handle. It is a fail-fast guard thrown before any upload is attempted.","triggerScenarios":"Running the upload command with a file whose extension (path.extname, lowercased) is absent from MIME_MAP, e.g. .pdf, .txt, .avi, .mkv, .heic, .jfif, or a file with no extension at all (mime = undefined).","commonSituations":"Uploading screenshots saved as .bmp or .tiff, camera footage as .mkv/.avi, HEIC iPhone photos, or files stripped of extensions during download; also typos in extension case are handled, but unusual variants like .jpeg? no — .jpeg maps, but .jfif does not.","solutions":["Convert the file to a supported format (jpg/png/gif/webp for images, mp4/mov for video) before uploading","Rename the file to use a supported extension if it is actually a supported format misnamed (e.g. a jpg saved as .jfif is not mapped — convert, don't rename blindly)","Check the extension with `ls`/`file` to confirm the actual format, since path.extname trusts the name not the content","Upload via URL instead if the format cannot be converted"],"exampleFix":"// before\nyollomi upload ./notes.pdf\n// throws INVALID_TYPE\n// after\nconvert notes.pdf notes.png   # e.g. with ImageMagick\nyollomi upload ./notes.png","handlingStrategy":"validation","validationCode":"const SUPPORTED = ['.jpg','.png','.gif','.webp','.mp4','.mov'];\nif (!SUPPORTED.includes(path.extname(file).toLowerCase())) {\n  throw new Error(`Convert ${file}: extension ${path.extname(file)} not supported`);\n}","typeGuard":"function isSupportedMedia(file) {\n  return ['.jpg','.png','.gif','.webp','.mp4','.mov']\n    .includes(path.extname(file).toLowerCase());\n}","tryCatchPattern":"try {\n  await upload(file);\n} catch (e) {\n  if (e.code === 'INVALID_TYPE') console.error(`Unsupported type: convert ${file} to jpg/png/gif/webp/mp4/mov`);\n  else throw e;\n}","preventionTips":["Normalize/convert media to jpg or mp4 before any upload pipeline","Check extensions with `file` command so content matches the name","Keep a pre-upload whitelist check in scripts mirroring MIME_MAP"],"tags":["cli","file-upload","validation","unsupported-file-type"],"backgroundTag":"unsupported-file-type","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}