{"record":{"id":"52ce88df3671a2bd","repo":"jackwener/OpenCLI","slug":"midjourney-raw-video-returned-invalid-mp4-bytes-fr","errorCode":null,"errorMessage":"Midjourney raw video returned invalid MP4 bytes from ${url}","messagePattern":"Midjourney raw video returned invalid MP4 bytes from (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/midjourney/utils.js","lineNumber":720,"sourceCode":"  try {\n    await fs.writeFile(tempPath, buffer);\n    await fs.rename(tempPath, filePath);\n  } catch (error) {\n    await fs.unlink(tempPath).catch(() => {});\n    throw new CommandExecutionError(`Could not write Midjourney media ${filePath}: ${errorMessage(error)}`);\n  }\n}\n\nexport async function downloadRawVideo(page, jobId, index, outputDir, force = false) {\n  await fs.mkdir(outputDir, { recursive: true });\n  const url = rawVideoUrl(jobId, index);\n  const filePath = path.join(outputDir, `${jobId}_${index + 1}_raw.mp4`);\n  const existing = await existingMedia(filePath, force, 'video/mp4');\n  if (existing) return { index, kind: 'video-raw', filePath, bytes: existing.size, url, mime: 'video/mp4', cached: true };\n  const media = await fetchMediaThroughPage(page, url, 'video/');\n  const actualMime = sniffMediaMime(media.buffer);\n  if (actualMime !== 'video/mp4') {\n    throw new CommandExecutionError(`Midjourney raw video returned invalid MP4 bytes from ${url}`);\n  }\n  if (media.mime !== actualMime) {\n    log.warn(`Midjourney CDN reported ${media.mime || 'unknown'} for ${url}; detected ${actualMime} from file bytes`);\n  }\n  await writeMediaBuffer(filePath, media.buffer);\n  return { index, kind: 'video-raw', filePath, bytes: media.buffer.length, url, mime: actualMime, cached: false };\n}\n\nexport async function downloadRenderedVideo(page, jobId, index, kind, outputDir, force = false) {\n  const config = kind === 'video-social'\n    ? { label: 'Download for Social', extension: '.mp4', mime: 'video/mp4' }\n    : kind === 'gif'\n      ? { label: 'Download as GIF', extension: '.gif', mime: 'image/gif' }\n      : null;\n  if (!config) throw new ArgumentError('Rendered video kind must be video-social or gif');\n  await fs.mkdir(outputDir, { recursive: true });\n  const filePath = path.join(outputDir, `${jobId}_${index + 1}_${kind.replace('video-', '')}${config.extension}`);\n  const existing = await existingMedia(filePath, force, config.mime);","sourceCodeStart":702,"sourceCodeEnd":738,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/midjourney/utils.js#L702-L738","documentation":"Thrown by the raw-video download path when the bytes fetched from the Midjourney CDN via the browser page do not sniff as video/mp4. The library validates the magic bytes of every downloaded raw video before writing it to disk, guarding against HTML error pages, expired-CDN responses, or truncated downloads being cached as valid MP4s. It indicates the CDN did not serve a genuine MP4 for that media URL.","triggerScenarios":"downloadRawVideo fetches a raw video URL with fetchMediaThroughPage and sniffMediaMime(buffer) returns something other than 'video/mp4' (e.g. 'text/html', 'image/webp', or 'unknown').","commonSituations":"Expired Midjourney CDN links returning an HTML error page; session cookies missing so the CDN returns a login/redirect page; the CDN serving WebM or fragmented MP4 variants whose magic bytes the sniffer does not recognize; a proxy or corporate TLS interceptor replacing the response body.","solutions":["Re-run the command with a fresh authenticated browser session so the CDN serves the real video instead of an error page","Check what the URL actually returns (curl -I) — if text/html, the CDN link has expired; re-open the job page to get a fresh URL","Log or inspect the sniffed actualMime to identify the real content type and, if it is a supported-but-unlabeled variant, extend sniffMediaMime","Disable interfering proxies/MITM tools and retry","Delete any partially-written output file and retry with force to bypass the cache"],"exampleFix":"// before\nif (actualMime !== 'video/mp4') {\n  throw new CommandExecutionError(`Midjourney raw video returned invalid MP4 bytes from ${url}`);\n}\n// after\nif (actualMime !== 'video/mp4') {\n  log.warn(`Retrying fetch for ${url}; got ${actualMime}`);\n  const retry = await fetchMediaThroughPage(page, url, 'video/');\n  if (sniffMediaMime(retry.buffer) !== 'video/mp4') {\n    throw new CommandExecutionError(`Midjourney raw video returned invalid MP4 bytes from ${url} (got ${actualMime})`);\n  }\n  media.buffer = retry.buffer;\n}","handlingStrategy":"validation","validationCode":"const res = await fetch(url, { headers: { cookie: sessionCookie } });\nconst head = Buffer.from(await res.arrayBuffer()).subarray(0, 16);\nconst isMp4 = head.subarray(4, 8).toString('binary') === 'ftyp';\nif (!isMp4) throw new Error(`URL ${url} is not serving MP4 (content-type ${res.headers.get('content-type')})`);","typeGuard":"function isMp4Buffer(buf) {\n  return buf.length > 11 && buf.subarray(4, 8).toString('binary') === 'ftyp';\n}","tryCatchPattern":"try {\n  const result = await downloadRawVideo(page, url, jobId, index, outputDir);\n} catch (err) {\n  if (err.message.includes('invalid MP4 bytes')) {\n    await refreshSession(page);\n    return downloadRawVideo(page, url, jobId, index, outputDir, true);\n  }\n  throw err;\n}","preventionTips":["Keep the browser session authenticated so CDN URLs resolve to media, not error pages","Use fresh job page URLs rather than long-lived CDN links that may have expired","Pre-validate media URLs with a HEAD request for content-type video/ before download","Clear stale cached output files with --force after session or CDN changes"],"tags":["midjourney","browser-automation","media-download","mp4-validation"],"backgroundTag":"invalid-media-bytes","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}