{"record":{"id":"ba5480232b6cf7fa","repo":"nexu-io/open-design","slug":"image-is-not-a-regular-file-rel","errorCode":null,"errorMessage":"--image is not a regular file: ${rel}","messagePattern":"--image is not a regular file: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/media/index.ts","lineNumber":237,"sourceCode":"  if (typeof rel !== 'string' || !rel.trim()) return null;\n  const projectRootResolved = path.resolve(projectDir);\n  const abs = path.resolve(projectRootResolved, rel.trim());\n  if (\n    abs !== projectRootResolved &&\n    !abs.startsWith(projectRootResolved + path.sep)\n  ) {\n    throw new Error(\n      `--image path \"${rel}\" resolves outside the project directory.`,\n    );\n  }\n  let info;\n  try {\n    info = await stat(abs);\n  } catch {\n    throw new Error(`--image not found: ${rel}`);\n  }\n  if (!info.isFile()) {\n    throw new Error(`--image is not a regular file: ${rel}`);\n  }\n  // Cap at 16 MB. Beyond this, base64 inflation alone (≈4/3) starts\n  // hitting body-size limits at the upstream APIs and our own express\n  // 4mb body cap on inbound requests; bigger payloads should travel\n  // via the dedicated upload endpoint, not the dispatcher.\n  const MAX_IMAGE_BYTES = 16 * 1024 * 1024;\n  if (info.size > MAX_IMAGE_BYTES) {\n    throw new Error(\n      `--image too large (${info.size} bytes; max ${MAX_IMAGE_BYTES}).`,\n    );\n  }\n  const bytes = await readFile(abs);\n  const ext = path.extname(abs).toLowerCase();\n  // Tight allowlist: only what i2v / image-edit endpoints actually\n  // consume. Avoids smuggling arbitrary content through as data URLs.\n  const mime = ({\n    '.png': 'image/png',\n    '.jpg': 'image/jpeg',","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/media/index.ts#L219-L255","documentation":"Thrown by resolveProjectImage when fs.stat succeeds but the entry is not a regular file (info.isFile() is false). The image pipeline can only stream regular file bytes; directories, symbolic links to directories, device/socket/pipe entries are rejected.","triggerScenarios":"Passing `--image assets/` (a directory); a path that resolves to a FIFO/socket; a dangling or directory-targeting symlink; pointing at a special device file.","commonSituations":"Agent passes a folder path instead of a file; symlink to a directory; OS-created socket/fifo at the path; misconfigured asset path.","solutions":["Point --image at a specific image file, not a directory.","Resolve symlinks and ensure the target is a regular file.","Remove accidental sockets/fifos from the asset path.","List the directory contents to find the actual image file."],"exampleFix":"// before\n--image assets/\n// after\n--image assets/hero.png","handlingStrategy":"validation","validationCode":"import { stat } from 'node:fs/promises';\nconst info = await stat(abs);\nif (!info.isFile()) throw new Error(`--image is not a regular file: ${rel}`);","typeGuard":"async function isRegularFile(abs: string): Promise<boolean> {\n  try { return (await stat(abs)).isFile(); } catch { return false; }\n}","tryCatchPattern":null,"preventionTips":["Point --image at a file, never a directory.","Resolve symlinks to ensure they target regular files.","Validate the asset path is a file in your UI before submit."],"tags":["media","files","validation"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}