jackwener/OpenCLI · error · ArgumentError

Unsupported story media format: ${ext}

Error message

Unsupported story media format: ${ext}

What it means

An ArgumentError thrown by normalizeStoryMediaItem() when the file extension is neither a supported story image (.jpg, .jpeg, .png, .webp) nor video (.mp4). Instagram's story API only accepts these formats, so unsupported types are rejected before upload.

Source

Thrown at clis/instagram/story.js:40

    const parts = raw.split(',').map((part) => part.trim()).filter(Boolean);
    if (parts.length === 0) {
        throw new ArgumentError('Argument "media" is required.', 'Provide --media /path/to/file.jpg or --media /path/to/file.mp4');
    }
    if (parts.length > 1) {
        throw new ArgumentError('Instagram story currently supports a single media item.', 'Provide one image or one video path with --media');
    }
    const resolved = path.resolve(parts[0]);
    if (!fs.existsSync(resolved)) {
        throw new ArgumentError(`Story media file not found: ${resolved}`);
    }
    const ext = path.extname(resolved).toLowerCase();
    if (SUPPORTED_STORY_IMAGE_EXTENSIONS.has(ext)) {
        return { type: 'image', filePath: resolved };
    }
    if (SUPPORTED_STORY_VIDEO_EXTENSIONS.has(ext)) {
        return { type: 'video', filePath: resolved };
    }
    throw new ArgumentError(`Unsupported story media format: ${ext}`, 'Supported formats: images (.jpg, .jpeg, .png, .webp) and videos (.mp4)');
}
async function resolveCurrentUsername(page, currentUserId = '') {
    if (!currentUserId)
        return '';
    const runtimeInfo = await resolveInstagramRuntimeInfo(page);
    const apiResult = await page.evaluate(`
    (async () => {
      const userId = ${JSON.stringify(currentUserId)};
      const appId = ${JSON.stringify(runtimeInfo.appId || '')};
      try {
        const res = await fetch(
          'https://www.instagram.com/api/v1/users/' + encodeURIComponent(userId) + '/info/',
          {
            credentials: 'include',
            headers: appId ? { 'X-IG-App-ID': appId } : {},
          },
        );
        if (!res.ok) return { ok: false };

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Convert the file: images to .jpg/.png (e.g. `sips -s format jpeg` or ImageMagick `convert`), videos to .mp4 (e.g. `ffmpeg -i in.mov out.mp4`)
  2. Rename the file so its extension matches its actual format (only if the format truly matches)
  3. Pre-check the extension in your script before calling the command and convert as needed
  4. Ensure the file has an extension at all

Example fix

// before
await story({ media: 'IMG_0001.HEIC' });
// after
execSync('magick IMG_0001.HEIC IMG_0001.jpg');
await story({ media: 'IMG_0001.jpg' });
Defensive patterns

Strategy: validation

Validate before calling

const ext = path.extname(mediaArg).toLowerCase();
const ok = ['.jpg', '.jpeg', '.png', '.webp', '.mp4'].includes(ext);
if (!ok) throw new Error(`Convert ${ext} files to jpg/png/webp (image) or mp4 (video) first`);

Type guard

function isSupportedStoryMedia(p) {
  const e = path.extname(p).toLowerCase();
  return ['.jpg', '.jpeg', '.png', '.webp', '.mp4'].includes(e);
}

Try / catch

try {
  await postStory({ media: file });
} catch (e) {
  if (/Unsupported story media format/.test(e.message)) {
    const out = file.replace(/\\.[^.]+$/, '.mp4');
    execSync(`ffmpeg -i ${file} ${out}`);
    await postStory({ media: out });
  } else throw e;
}

Prevention

When it happens

Trigger: --media points to an existing file whose extension (lowercased) is not in SUPPORTED_STORY_IMAGE_EXTENSIONS or SUPPORTED_STORY_VIDEO_EXTENSIONS, e.g. .gif, .heic, .mov, .pdf, or no extension.

Common situations: iPhone HEIC photos, .MOV videos from iOS, GIFs, or files with missing/uppercase-handled extensions; also raw downloaded files not yet converted.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/cb4ea556c28f0411. Report an issue: GitHub.