jackwener/OpenCLI · error · ArgumentError

Rendered video kind must be video-social or gif

Error message

Rendered video kind must be video-social or gif

What it means

An ArgumentError raised when downloadRenderedVideo is called with a kind argument other than 'video-social' or 'gif'. These are the only two rendered-download menu labels the function has configurations for; anything else would produce a null config and an unhandled null dereference later, so the function fails fast.

Source

Thrown at clis/midjourney/utils.js:735

  const media = await fetchMediaThroughPage(page, url, 'video/');
  const actualMime = sniffMediaMime(media.buffer);
  if (actualMime !== 'video/mp4') {
    throw new CommandExecutionError(`Midjourney raw video returned invalid MP4 bytes from ${url}`);
  }
  if (media.mime !== actualMime) {
    log.warn(`Midjourney CDN reported ${media.mime || 'unknown'} for ${url}; detected ${actualMime} from file bytes`);
  }
  await writeMediaBuffer(filePath, media.buffer);
  return { index, kind: 'video-raw', filePath, bytes: media.buffer.length, url, mime: actualMime, cached: false };
}

export async function downloadRenderedVideo(page, jobId, index, kind, outputDir, force = false) {
  const config = kind === 'video-social'
    ? { label: 'Download for Social', extension: '.mp4', mime: 'video/mp4' }
    : kind === 'gif'
      ? { label: 'Download as GIF', extension: '.gif', mime: 'image/gif' }
      : null;
  if (!config) throw new ArgumentError('Rendered video kind must be video-social or gif');
  await fs.mkdir(outputDir, { recursive: true });
  const filePath = path.join(outputDir, `${jobId}_${index + 1}_${kind.replace('video-', '')}${config.extension}`);
  const existing = await existingMedia(filePath, force, config.mime);
  if (existing) return { index, kind, filePath, bytes: existing.size, url: null, mime: config.mime, cached: true };

  await page.goto(jobUrl(jobId, index));
  await page.wait({ selector: 'video[src]', timeout: 20 });
  await page.click('button[title="Options"]');
  await page.wait(0.3);
  const marked = unwrapEvaluateResult(await page.evaluate((label) => {
    document.querySelectorAll('[data-opencli-video-download]').forEach((node) => node.removeAttribute('data-opencli-video-download'));
    const button = [...document.querySelectorAll('button[role="menuitem"],button')]
      .find((node) => node.textContent?.trim() === label && node.getBoundingClientRect().width > 0);
    if (!button) return false;
    button.setAttribute('data-opencli-video-download', '1');
    return true;
  }, config.label));
  if (!marked) throw new CommandExecutionError(`Midjourney did not expose "${config.label}" for video ${jobId}`);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass exactly 'video-social' or 'gif' as kind
  2. Normalize/whitelist the user-facing option before calling (map 'mp4'→'video-social', 'animated gif'→'gif')
  3. Add switch/case validation at the CLI boundary so invalid kinds never reach this function

Example fix

// before
await downloadRenderedVideo(page, id, i, 'mp4', outDir);
// after
const kind = format === 'gif' ? 'gif' : 'video-social';
await downloadRenderedVideo(page, id, i, kind, outDir);
Defensive patterns

Strategy: validation

Validate before calling

const RENDER_KINDS = ['video-social', 'gif'];
if (!RENDER_KINDS.includes(kind)) {
  throw new TypeError(`kind must be one of ${RENDER_KINDS.join(', ')}, got '${kind}'`);
}
await downloadRenderedVideo(page, jobId, index, kind, outputDir);

Type guard

function isRenderVideoKind(kind) {
  return kind === 'video-social' || kind === 'gif';
}

Try / catch

try {
  await downloadRenderedVideo(page, jobId, i, kind, outDir);
} catch (err) {
  if (err.name === 'ArgumentError' && err.message.includes('video-social or gif')) {
    console.error(`Bad kind '${kind}' — use 'video-social' or 'gif'`);
    process.exitCode = 2;
  } else throw err;
}

Prevention

When it happens

Trigger: Calling downloadRenderedVideo(page, jobId, index, kind, outputDir, force) with kind values like 'video', 'mp4', 'raw', or a typo such as 'videosocial'.

Common situations: Mapping a CLI flag or user-supplied string directly to kind without normalizing; mistaking the raw video path (which uses kind 'video-raw') for the rendered path; renaming the kind constants in a refactor without updating callers.

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/caebebf4cc59af13. Report an issue: GitHub.