{"record":{"id":"3411fdc57d53fc83","repo":"jackwener/OpenCLI","slug":"browser-reported-a-completed-download-but-the-file","errorCode":null,"errorMessage":"Browser reported a completed download but the file is missing: ${sourcePath}","messagePattern":"Browser reported a completed download but the file is missing: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/midjourney/utils.js","lineNumber":765,"sourceCode":"    const button = [...document.querySelectorAll('button[role=\"menuitem\"],button')]\n      .find((node) => node.textContent?.trim() === label && node.getBoundingClientRect().width > 0);\n    if (!button) return false;\n    button.setAttribute('data-opencli-video-download', '1');\n    return true;\n  }, config.label));\n  if (!marked) throw new CommandExecutionError(`Midjourney did not expose \"${config.label}\" for video ${jobId}`);\n  await page.click('[data-opencli-video-download=\"1\"]');\n  if (typeof page.waitForDownload !== 'function') {\n    throw new CommandExecutionError('Browser Bridge download lifecycle support is required for social video/GIF export');\n  }\n  const downloaded = await page.waitForDownload(jobId, 60_000);\n  if (!downloaded?.downloaded || downloaded.state !== 'complete' || !downloaded.filename) {\n    throw new CommandExecutionError(`Midjourney ${kind} download did not complete: ${downloaded?.error || downloaded?.state || 'unknown'}`);\n  }\n  const sourcePath = path.resolve(String(downloaded.filename));\n  const sourceStat = await fs.stat(sourcePath).catch(() => null);\n  if (!sourceStat?.isFile() || sourceStat.size <= 0) {\n    throw new CommandExecutionError(`Browser reported a completed download but the file is missing: ${sourcePath}`);\n  }\n  const handle = await fs.open(sourcePath, 'r');\n  let actualMime;\n  try {\n    const header = Buffer.alloc(16);\n    const { bytesRead } = await handle.read(header, 0, header.length, 0);\n    actualMime = sniffMediaMime(header.subarray(0, bytesRead));\n  } finally {\n    await handle.close();\n  }\n  if (actualMime !== config.mime) {\n    throw new CommandExecutionError(\n      `Midjourney ${kind} returned invalid media bytes; expected ${config.mime}, detected ${actualMime || 'unknown'}`,\n    );\n  }\n  if (downloaded.mime && downloaded.mime !== actualMime) {\n    log.warn(`Browser Bridge reported ${downloaded.mime} for ${sourcePath}; detected ${actualMime} from file bytes`);\n  }","sourceCodeStart":747,"sourceCodeEnd":783,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/midjourney/utils.js#L747-L783","documentation":"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.","triggerScenarios":"fs.stat(sourcePath) rejects (path resolves to null) or the stat shows size <= 0 immediately after waitForDownload reported state 'complete'.","commonSituations":"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.","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"],"exampleFix":"// before\nconst sourceStat = await fs.stat(sourcePath).catch(() => null);\nif (!sourceStat?.isFile() || sourceStat.size <= 0) throw ...;\n// after\nlet sourceStat = null;\nfor (let i = 0; i < 5 && !sourceStat; i++) {\n  await new Promise((r) => setTimeout(r, 500));\n  sourceStat = await fs.stat(sourcePath).catch(() => null);\n}\nif (!sourceStat?.isFile() || sourceStat.size <= 0) throw ...;","handlingStrategy":"retry","validationCode":"const stat = await fs.promises.stat(bridgeDownloadDir).catch(() => null);\nif (!stat?.isDirectory()) throw new Error('Browser download directory is not accessible from this process');","typeGuard":"async function downloadedFileReady(p) {\n  const s = await fs.promises.stat(p).catch(() => null);\n  return Boolean(s?.isFile() && s.size > 0);\n}","tryCatchPattern":"try {\n  await downloadRenderedVideo(page, jobId, i, kind, outDir);\n} catch (err) {\n  if (err.message.includes('file is missing')) {\n    console.error(`Browser download path unreachable: ${err.message}. Check sandbox (snap/flatpak) path mapping.`);\n  } else throw err;\n}","preventionTips":["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"],"tags":["filesystem","download-failed","browser-bridge","race-condition"],"backgroundTag":"downloaded-file-missing","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}