jackwener/OpenCLI · error · ArgumentError

Instagram story currently supports a single media item.

Error message

Instagram story currently supports a single media item.

What it means

An ArgumentError thrown by normalizeStoryMediaItem() when the --media value contains more than one comma-separated path. The story upload path currently supports exactly one image or one video per post, so multi-item input is rejected early with guidance to pass a single path.

Source

Thrown at clis/instagram/story.js:27

const SUPPORTED_STORY_VIDEO_EXTENSIONS = new Set(['.mp4']);
function requirePage(page) {
    if (!page)
        throw new CommandExecutionError('Browser session required for instagram story');
    return page;
}
function validateInstagramStoryArgs(kwargs) {
    if (kwargs.media === undefined) {
        throw new ArgumentError('Argument "media" is required.', 'Provide --media /path/to/file.jpg or --media /path/to/file.mp4');
    }
}
function normalizeStoryMediaItem(kwargs) {
    const raw = String(kwargs.media ?? '').trim();
    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);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass exactly one file path: --media /path/to/photo.jpg
  2. Call the story command once per media item
  3. Expand globs yourself and iterate, invoking the command per file
  4. Remove accidental trailing/extra commas from the value

Example fix

// before
await story({ media: 'a.jpg,b.jpg' });
// after
for (const f of ['a.jpg', 'b.jpg']) {
  await story({ media: f });
}
Defensive patterns

Strategy: validation

Validate before calling

const parts = String(kwargs?.media ?? '').split(',').map(s => s.trim()).filter(Boolean);
if (parts.length > 1) throw new Error('Pass one media file per story command');

Type guard

function isSingleMedia(v) { return typeof v === 'string' && v.split(',').filter(s => s.trim()).length === 1; }

Try / catch

try {
  await postStory({ media: files });
} catch (e) {
  if (/single media item/.test(e.message)) {
    for (const f of files.split(',')) await postStory({ media: f.trim() });
  } else throw e;
}

Prevention

When it happens

Trigger: kwargs.media splits into 2+ non-empty parts, e.g. --media 'a.jpg,b.jpg' or a stray comma like 'photo.jpg,' followed by another value.

Common situations: Trying to post multiple stories in one command, globbing patterns expanding to several files, or copy-pasting a comma-separated list intended for another command.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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