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
- Pass exactly 'video-social' or 'gif' as kind
- Normalize/whitelist the user-facing option before calling (map 'mp4'→'video-social', 'animated gif'→'gif')
- 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
- Centralize the kind constants and import them rather than inlining strings
- Normalize CLI flags to the canonical kinds at the argument-parsing boundary
- Add a unit test covering every user-facing format option mapping to a valid kind
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
- operation must be one of: ${ACTION_CHOICES.join(', ')}
- 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
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/caebebf4cc59af13.
Report an issue: GitHub.