jackwener/OpenCLI · error · CommandExecutionError

Could not write Midjourney media ${filePath}: ${errorMessage

Error message

Could not write Midjourney media ${filePath}: ${errorMessage(error)}

What it means

Same as the image variant: writing the media bytes (video/other) to filePath failed at the OS level during the temp-file write or atomic rename. The .part temp file is removed before throwing a CommandExecutionError with the underlying reason.

Source

Thrown at clis/midjourney/utils.js:707

export async function downloadOriginals(page, jobId, indices, outputDir, force = false) {
  await fs.mkdir(outputDir, { recursive: true });
  const files = [];
  for (const index of indices) files.push(await downloadOne(page, jobId, index, outputDir, force));
  return files;
}

export function rawVideoUrl(jobId, index) {
  return `${MIDJOURNEY_CDN}/video/${jobId}/${index}.mp4`;
}

async function writeMediaBuffer(filePath, buffer) {
  const tempPath = `${filePath}.part-${process.pid}-${Date.now()}`;
  try {
    await fs.writeFile(tempPath, buffer);
    await fs.rename(tempPath, filePath);
  } catch (error) {
    await fs.unlink(tempPath).catch(() => {});
    throw new CommandExecutionError(`Could not write Midjourney media ${filePath}: ${errorMessage(error)}`);
  }
}

export async function downloadRawVideo(page, jobId, index, outputDir, force = false) {
  await fs.mkdir(outputDir, { recursive: true });
  const url = rawVideoUrl(jobId, index);
  const filePath = path.join(outputDir, `${jobId}_${index + 1}_raw.mp4`);
  const existing = await existingMedia(filePath, force, 'video/mp4');
  if (existing) return { index, kind: 'video-raw', filePath, bytes: existing.size, url, mime: 'video/mp4', cached: true };
  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);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Free disk space (videos are large; ENOSPC is the most common cause).
  2. Verify the output directory exists and is writable.
  3. Fix permissions/ownership of the output directory.
  4. Ensure the destination filesystem supports atomic rename on the same mount as the temp file.

Example fix

// before
await downloadRawVideo(page, jobId, 0, fullDiskDir);
// after
await ensureFreeSpace(dir, requiredBytes);
await downloadRawVideo(page, jobId, 0, dir);
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'node:fs/promises';
await fs.mkdir(outputDir, { recursive: true });
await fs.access(outputDir, fs.constants.W_OK);

Try / catch

try {
  await downloadRawVideo(page, jobId, index, outDir);
} catch (err) {
  if (/Could not write Midjourney media/.test(err.message)) {
    if (err.message.includes('ENOSPC')) throw new Error('Disk full: free space before retry');
    await fs.mkdir(outDir, { recursive: true });
    await downloadRawVideo(page, jobId, index, outDir);
  } else throw err;
}

Prevention

When it happens

Trigger: Disk full while writing a large video (ENOSPC); permission denied in the output directory; rename across filesystems; path is a directory or locked by another process.

Common situations: Videos are large, so disk-quota exhaustion is more common here than for images; shared network mounts with flaky write support; output directories created with wrong ownership in containers.

Related errors


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