{"record":{"id":"b1e5654dc41b17fe","repo":"jackwener/OpenCLI","slug":"label-must-be-png-jpeg-webp-or-gif-ref-va","errorCode":null,"errorMessage":"${label} must be PNG, JPEG, WEBP, or GIF: ${ref.value}","messagePattern":"(.+?) must be PNG, JPEG, WEBP, or GIF: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/midjourney/utils.js","lineNumber":915,"sourceCode":"      return { kind: 'url', value: item };\n    }\n    const expanded = item === '~' ? os.homedir() : item.startsWith('~/') ? path.join(os.homedir(), item.slice(2)) : item;\n    return { kind: 'local', value: path.resolve(expanded) };\n  });\n}\n\nexport async function validateLocalReferences(refs, label) {\n  for (const ref of refs.filter((item) => item.kind === 'local')) {\n    let stat;\n    try {\n      stat = await fs.stat(ref.value);\n    } catch {\n      throw new ArgumentError(`${label} file does not exist: ${ref.value}`);\n    }\n    if (!stat.isFile() || stat.size <= 0) throw new ArgumentError(`${label} must reference a non-empty file: ${ref.value}`);\n    if (stat.size > MAX_REFERENCE_BYTES) throw new ArgumentError(`${label} exceeds Midjourney's 10MB upload limit: ${ref.value}`);\n    const ext = path.extname(ref.value).toLowerCase();\n    if (!IMAGE_EXTENSIONS.has(ext)) throw new ArgumentError(`${label} must be PNG, JPEG, WEBP, or GIF: ${ref.value}`);\n  }\n  return refs;\n}\n\nasync function visibleImageSources(page) {\n  const payload = unwrapEvaluateResult(await page.evaluate(() => [...document.querySelectorAll('img[src]')]\n    .filter((img) => {\n      const rect = img.getBoundingClientRect();\n      let card = img.parentElement;\n      while (card && !String(card.className).includes('group/img')) card = card.parentElement;\n      return Boolean(card) && rect.width > 24 && rect.height > 24 && /cdn\\.midjourney\\.com\\/u\\//.test(img.src);\n    })\n    .map((img) => img.src)));\n  return Array.isArray(payload) ? payload.map(String) : [];\n}\n\nexport async function openImagePanel(page) {\n  const markInput = async () => unwrapEvaluateResult(await page.evaluate(() => {","sourceCodeStart":897,"sourceCodeEnd":933,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/midjourney/utils.js#L897-L933","documentation":"Midjourney only accepts PNG, JPEG, WEBP, and GIF uploads. The validator checks the lowercased file extension against the IMAGE_EXTENSIONS set and throws this ArgumentError for anything else — including SVG, HEIC, TIFF, AVIF, BMP, and PDF — before any upload is attempted.","triggerScenarios":"A local file with an unsupported extension: .svg, .heic (iPhone photos), .tiff, .avif, .bmp, .pdf, or a file with no extension at all.","commonSituations":"iOS photos synced as HEIC, Figma exports as SVG/PDF, scanner output as TIFF, modern AVIF saves, or extensionless files downloaded without names.","solutions":["Convert to a supported format (magick input.heic output.png; ffmpeg -i in.tiff out.png)","Rename with a correct supported extension if the content is actually PNG/JPEG/WEBP/GIF but mislabeled","Export from the source tool as PNG/JPEG rather than SVG/PDF"],"exampleFix":"// before\nclis/midjourney --refs ./photo.heic\n// after\nmagick ./photo.heic ./photo.png\nclis/midjourney --refs ./photo.png","handlingStrategy":"validation","validationCode":"const ALLOWED = new Set(['.png', '.jpeg', '.jpg', '.webp', '.gif']);\nconst ext = path.extname(p).toLowerCase();\nif (!ALLOWED.has(ext)) throw new Error(`${p}: convert to PNG/JPEG/WEBP/GIF first`);","typeGuard":"const hasSupportedImageExt = (p) => ['.png', '.jpeg', '.jpg', '.webp', '.gif'].includes(path.extname(p).toLowerCase());","tryCatchPattern":"try {\n  await validateLocalReferences(refs, 'refs');\n} catch (e) {\n  if (String(e.message).includes('must be PNG, JPEG, WEBP, or GIF')) {\n    console.error('Convert the file, e.g. magick input.heic output.png');\n  }\n  throw e;\n}","preventionTips":["Convert HEIC/TIFF/SVG/AVIF sources to PNG/JPEG before uploading","Normalize extensions when ingesting files from phones or design tools","Keep an automated transcode step in pipelines that accept arbitrary images"],"tags":["filesystem","argument-validation","file-format"],"backgroundTag":"unsupported-file-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}