jackwener/OpenCLI · error · CommandExecutionError

Midjourney ${kind} returned invalid media bytes; expected ${

Error message

Midjourney ${kind} returned invalid media bytes; expected ${config.mime}, detected ${actualMime || 'unknown'}

What it means

A CommandExecutionError thrown when the downloaded rendered video's magic bytes do not match the expected MIME for the requested kind — video/mp4 for 'video-social' or image/gif for 'gif'. Like the raw-video check, this prevents saving HTML error pages or wrongly-typed responses as media files.

Source

Thrown at clis/midjourney/utils.js:777

  if (!downloaded?.downloaded || downloaded.state !== 'complete' || !downloaded.filename) {
    throw new CommandExecutionError(`Midjourney ${kind} download did not complete: ${downloaded?.error || downloaded?.state || 'unknown'}`);
  }
  const sourcePath = path.resolve(String(downloaded.filename));
  const sourceStat = await fs.stat(sourcePath).catch(() => null);
  if (!sourceStat?.isFile() || sourceStat.size <= 0) {
    throw new CommandExecutionError(`Browser reported a completed download but the file is missing: ${sourcePath}`);
  }
  const handle = await fs.open(sourcePath, 'r');
  let actualMime;
  try {
    const header = Buffer.alloc(16);
    const { bytesRead } = await handle.read(header, 0, header.length, 0);
    actualMime = sniffMediaMime(header.subarray(0, bytesRead));
  } finally {
    await handle.close();
  }
  if (actualMime !== config.mime) {
    throw new CommandExecutionError(
      `Midjourney ${kind} returned invalid media bytes; expected ${config.mime}, detected ${actualMime || 'unknown'}`,
    );
  }
  if (downloaded.mime && downloaded.mime !== actualMime) {
    log.warn(`Browser Bridge reported ${downloaded.mime} for ${sourcePath}; detected ${actualMime} from file bytes`);
  }
  const tempPath = `${filePath}.part-${process.pid}-${Date.now()}`;
  try {
    await fs.copyFile(sourcePath, tempPath);
    await fs.rename(tempPath, filePath);
    if (sourcePath !== filePath) await fs.unlink(sourcePath).catch(() => {});
  } catch (error) {
    await fs.unlink(tempPath).catch(() => {});
    throw new CommandExecutionError(`Could not store Midjourney ${kind} at ${filePath}: ${errorMessage(error)}`);
  }
  return {
    index,
    kind,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Compare the detected actualMime in the message with what Midjourney's UI really produces and update config.mime/extension if the format changed
  2. Re-authenticate and retry — an HTML result usually means the session dropped
  3. Open the downloaded file in a hex editor to confirm the actual format and adjust the sniffer if it's a valid but unrecognized variant
  4. Check file size — a tiny file is likely an error page, not media
  5. Retry the download; transient failures can yield empty/HTML bodies
Defensive patterns

Strategy: validation

Validate before calling

async function sniffIsKind(filePath, kind) {
  const fh = await fs.promises.open(filePath, 'r');
  try {
    const header = Buffer.alloc(16);
    const { bytesRead } = await fh.read(header, 0, 16, 0);
    const mime = sniffMediaMime(header.subarray(0, bytesRead));
    const expected = kind === 'gif' ? 'image/gif' : 'video/mp4';
    return mime === expected;
  } finally { await fh.close(); }
}

Type guard

function isGifHeader(buf) {
  return buf.subarray(0, 3).toString('binary') === 'GIF';
}
function isMp4Header(buf) {
  return buf.length > 11 && buf.subarray(4, 8).toString('binary') === 'ftyp';
}

Try / catch

try {
  await downloadRenderedVideo(page, jobId, i, kind, outDir);
} catch (err) {
  if (err.message.includes('invalid media bytes')) {
    const m = err.message.match(/detected ([^\s]+)/);
    console.error(`Midjourney sent ${m?.[1]} for kind '${kind}' — check for UI format changes or a dropped session.`);
  } else throw err;
}

Prevention

When it happens

Trigger: After a reported-complete download, sniffMediaMime(header) on the first bytes of the file returns anything other than config.mime (e.g. HTML masquerading as a download, or the browser saved a PNG when GIF was requested).

Common situations: Midjourney served an error/redirect page that the browser saved as the download; the 'Download as GIF' menu actually produces a WebP/APNG in a newer UI; the social MP4 export returned a WebM; corrupted or truncated file whose header doesn't parse.

Related errors


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