jackwener/OpenCLI · error · CommandExecutionError
Browser reported a completed download but the file is missin
Error message
Browser reported a completed download but the file is missing: ${sourcePath} What it means
A CommandExecutionError raised when the Browser Bridge reports a completed download with a filename, but fs.stat on the resolved path finds no regular file or a zero-byte file. This guards against trusting the bridge's success report when the file was moved, deleted, or never actually flushed to disk.
Source
Thrown at clis/midjourney/utils.js:765
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}`);
await page.click('[data-opencli-video-download="1"]');
if (typeof page.waitForDownload !== 'function') {
throw new CommandExecutionError('Browser Bridge download lifecycle support is required for social video/GIF export');
}
const downloaded = await page.waitForDownload(jobId, 60_000);
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`);
}View on GitHub (pinned to 49907e53dc)
Solutions
- Add a small delay/retry loop around fs.stat to allow the file to finish flushing
- If using a snap/flatpak-packaged browser, resolve the downloaded path against the browser's real download directory rather than path.resolve
- Check antivirus quarantine logs and exclude the download directory
- Verify the bridge returns an absolute filename; adapt if it reports only a basename
- Re-run the download; a zero-byte file usually indicates a transient failure
Example fix
// before
const sourceStat = await fs.stat(sourcePath).catch(() => null);
if (!sourceStat?.isFile() || sourceStat.size <= 0) throw ...;
// after
let sourceStat = null;
for (let i = 0; i < 5 && !sourceStat; i++) {
await new Promise((r) => setTimeout(r, 500));
sourceStat = await fs.stat(sourcePath).catch(() => null);
}
if (!sourceStat?.isFile() || sourceStat.size <= 0) throw ...; Defensive patterns
Strategy: retry
Validate before calling
const stat = await fs.promises.stat(bridgeDownloadDir).catch(() => null);
if (!stat?.isDirectory()) throw new Error('Browser download directory is not accessible from this process'); Type guard
async function downloadedFileReady(p) {
const s = await fs.promises.stat(p).catch(() => null);
return Boolean(s?.isFile() && s.size > 0);
} Try / catch
try {
await downloadRenderedVideo(page, jobId, i, kind, outDir);
} catch (err) {
if (err.message.includes('file is missing')) {
console.error(`Browser download path unreachable: ${err.message}. Check sandbox (snap/flatpak) path mapping.`);
} else throw err;
} Prevention
- Use a non-sandboxed browser (deb/npm-installed Chromium) so download paths map to the host filesystem
- Verify the bridge reports absolute download filenames
- Exclude the browser download directory from antivirus real-time scanning
- Wait for browser download finalization before inspecting or copying the file
When it happens
Trigger: fs.stat(sourcePath) rejects (path resolves to null) or the stat shows size <= 0 immediately after waitForDownload reported state 'complete'.
Common situations: The browser's download temp file was still being finalized when stat ran (race); the browser downloaded to a sandboxed/virtual filesystem (snap/flatpak Chromium) whose path differs from the host path; antivirus quarantined the file; the bridge reported a relative or stale filename.
Related errors
- Gmail ${operation} response body was unavailable
- target appeared during reservation
- output path is not a safe directory: ${resolved}
- Failed to write Pixiv novel ${path.basename(plan.destPath)}:
- Suno download wrote no files for clip ${clipId}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/3411fdc57d53fc83.
Report an issue: GitHub.