{"record":{"id":"12488bf57924b81f","repo":"jackwener/OpenCLI","slug":"unsupported-video-format-ext","errorCode":null,"errorMessage":"Unsupported video format: ${ext}","messagePattern":"Unsupported video format: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/instagram/reel.js","lineNumber":27,"sourceCode":"import { INSTAGRAM_HOME_URL, gotoInstagramHome } from './_shared/navigation.js';\nconst SUPPORTED_VIDEO_EXTENSIONS = new Set(['.mp4']);\nconst INSTAGRAM_REEL_TIMEOUT_SECONDS = 600;\nfunction requirePage(page) {\n    if (!page)\n        throw new CommandExecutionError('Browser session required for instagram reel');\n    return page;\n}\nfunction validateVideoPath(input) {\n    const resolved = path.resolve(String(input || '').trim());\n    if (!resolved) {\n        throw new ArgumentError('Video path cannot be empty');\n    }\n    if (!fs.existsSync(resolved)) {\n        throw new ArgumentError(`Video file not found: ${resolved}`);\n    }\n    const ext = path.extname(resolved).toLowerCase();\n    if (!SUPPORTED_VIDEO_EXTENSIONS.has(ext)) {\n        throw new ArgumentError(`Unsupported video format: ${ext}`, 'Supported formats: .mp4');\n    }\n    return resolved;\n}\nfunction validateInstagramReelArgs(kwargs) {\n    if (kwargs.video === undefined) {\n        throw new ArgumentError('Argument \"video\" is required.', 'Provide --video /path/to/file.mp4');\n    }\n}\nfunction buildInstagramReelSuccessResult(url) {\n    return [{\n            status: '✅ Posted',\n            detail: 'Single reel shared successfully',\n            url,\n        }];\n}\nfunction isRecoverableReelSessionError(error) {\n    if (!(error instanceof CommandExecutionError))\n        return false;","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/instagram/reel.js#L9-L45","documentation":"validateVideoPath only allows extensions in SUPPORTED_VIDEO_EXTENSIONS (currently just .mp4). If the resolved file has another extension it throws ArgumentError with the actual extension and a hint that .mp4 is required. This reflects Instagram's reel upload constraints and the uploader's tested format.","triggerScenarios":"Passing --video with .mov, .avi, .mkv, .webm, .m4v or any non-.mp4 extension (case-insensitive check).","commonSituations":"Screen recordings exported as .mov (macOS), videos downloaded as .webm/.mkv, or files with uppercase extensions like .MP4 (those pass, since ext is lowercased) — but genuinely non-mp4 containers fail.","solutions":["Convert the video to MP4 (e.g. ffmpeg -i input.mov -c:v libx264 -c:a aac output.mp4).","Rename only if the container is actually MPEG-4 but mislabeled; otherwise re-encode.","Export/record in MP4 format directly from the source tool."],"exampleFix":"// before\nawait reel({ video: 'screen-recording.mov' });\n// after\n// ffmpeg -i screen-recording.mov -c:v libx264 -c:a aac screen-recording.mp4\nawait reel({ video: 'screen-recording.mp4' });","handlingStrategy":"validation","validationCode":"if (path.extname(args.video).toLowerCase() !== '.mp4') throw new Error('Only .mp4 videos are supported; re-encode with ffmpeg');","typeGuard":null,"tryCatchPattern":"try { await reel(args); } catch (e) { if (e.message.startsWith('Unsupported video format')) { console.error('Convert to mp4: ffmpeg -i in.<ext> -c:v libx264 -c:a aac out.mp4'); return; } throw e; }","preventionTips":["Standardize on .mp4 (H.264/AAC) for all uploads","Add an extension check to your upload wrapper","Convert .mov/.webm/.mkv sources as an ingest step"],"tags":["unsupported-format","argument-validation","instagram"],"backgroundTag":"unsupported-file-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}