jackwener/OpenCLI · error · ArgumentError
Unsupported media format: ${ext}
Error message
Unsupported media format: ${ext} What it means
After confirming the media file exists, validateMixedMediaItems checks its lowercase extension against SUPPORTED_IMAGE_EXTENSIONS (.jpg/.jpeg/.png/.webp) and SUPPORTED_VIDEO_EXTENSIONS (.mp4). Any other extension throws ArgumentError with the offending extension and a hint listing supported formats. Extension, not MIME type, is the sole discriminator.
Source
Thrown at clis/instagram/post.js:109
if (inputs.length > MAX_MEDIA_ITEMS) {
throw new ArgumentError(`Too many media items: ${inputs.length}`, `Instagram carousel posts support at most ${MAX_MEDIA_ITEMS} items`);
}
const items = inputs.map((input) => {
const resolved = path.resolve(String(input || '').trim());
if (!resolved) {
throw new ArgumentError('Media path cannot be empty');
}
if (!fs.existsSync(resolved)) {
throw new ArgumentError(`Media file not found: ${resolved}`);
}
const ext = path.extname(resolved).toLowerCase();
if (SUPPORTED_IMAGE_EXTENSIONS.has(ext)) {
return { type: 'image', filePath: resolved };
}
if (SUPPORTED_VIDEO_EXTENSIONS.has(ext)) {
return { type: 'video', filePath: resolved };
}
throw new ArgumentError(`Unsupported media format: ${ext}`, 'Supported formats: images (.jpg, .jpeg, .png, .webp) and videos (.mp4)');
});
return items;
}
function normalizePostMediaItems(kwargs) {
const media = String(kwargs.media ?? '').trim();
return validateMixedMediaItems(media.split(',').map((part) => part.trim()).filter(Boolean));
}
function validateInstagramPostArgs(kwargs) {
const media = kwargs.media;
if (media === undefined) {
throw new ArgumentError('Argument "media" is required.', 'Provide --media /path/to/file.jpg or --media /path/a.jpg,/path/b.mp4');
}
}
function isSafePrivateRouteFallbackError(error) {
if (!(error instanceof CommandExecutionError))
return false;
return error.message.startsWith('Instagram private publish')
|| error.message.startsWith('Instagram private route');View on GitHub (pinned to 49907e53dc)
Solutions
- Convert the file: images to .jpg/.png/.webp, videos to .mp4 (e.g. ffmpeg -i clip.mov clip.mp4)
- Rename the file so its extension matches its true format if it is actually supported
- For HEIC use sips -s format jpeg photo.heic --out photo.jpg (macOS) or ImageMagick convert
- Do not try .gif; Instagram carousels via this CLI do not accept it
Example fix
// before --media /photos/clip.mov // after (shell) ffmpeg -i /photos/clip.mov -c:v libx264 /photos/clip.mp4 --media /photos/clip.mp4
Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED = new Set(['.jpg', '.jpeg', '.png', '.webp', '.mp4']);
function assertSupportedMedia(media) {
for (const p of String(media).split(',').map(s => s.trim()).filter(Boolean)) {
const ext = path.extname(p).toLowerCase();
if (!SUPPORTED.has(ext)) throw new Error(`Unsupported media format: ${ext} (${p})`);
}
}
assertSupportedMedia(media); Type guard
function hasSupportedExtension(p) {
return ['.jpg','.jpeg','.png','.webp','.mp4'].includes(path.extname(p).toLowerCase());
} Try / catch
try {
await cli.post({ media });
} catch (e) {
if (e instanceof ArgumentError && e.message.startsWith('Unsupported media format')) {
console.error('Convert to jpg/png/webp/mp4 first. Details:', e.message);
} else throw e;
} Prevention
- Convert HEIC/MOV/GIF inputs to jpg/mp4 at ingestion time in pipelines
- Check extensions (case-insensitively) before passing media lists
- Avoid double extensions like photo.jpg.txt
- Remember .gif is not accepted for carousels via this CLI
When it happens
Trigger: Passing --media with a file whose extension is .gif, .mov, .avi, .heic, .bmp, or a file with no extension at all — even if the actual content is a supported image/video.
Common situations: iPhone HEIC photos; screen recordings saved as .mov; GIFs users expect Instagram to accept; renamed files that lost their extension; double extensions like photo.jpg.txt.
Related errors
- archive search sort must be one of ${SORT_OPTIONS.join(', ')
- archive search mediatype must be one of ${MEDIATYPES.join(',
- archive search limit must be a positive integer
- archive search limit must be <= 100
- archive search query must not be empty
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/b7756e5c107d9d3f.
Report an issue: GitHub.