{"record":{"id":"b743360979f7c1b4","repo":"chatboxai/chatbox","slug":"file-is-not-an-image","errorCode":null,"errorMessage":"file is not an image","messagePattern":"file is not an image","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderer/packages/pic_utils.ts","lineNumber":8,"sourceCode":"/**\n * 获取图片base64，在必要时缩小到主流模型支持的尺寸，同时支持将 svg、gif 等文件转成 png 格式\n * @param file 图片文件\n * @returns 图片base64\n */\nexport async function getImageBase64AndResize(file: File) {\n  if (!file.type.startsWith('image/')) {\n    throw new Error('file is not an image')\n  }\n  // Claude: To improve time-to-first-token, we recommend resizing images to no more than 1.15 megapixels (and within 1568 pixels in both dimensions).\n  // https://docs.anthropic.com/en/docs/build-with-claude/vision\n  const maxPixelL1 = 1568\n  // OpenAI: For high res mode, the short side of the image should be less than 768px and the long side should be less than 2,000px.\n  // https://platform.openai.com/docs/guides/vision\n  const maxPixelL2 = 768\n  return new Promise<string>((resolve, reject) => {\n    const canvas = document.createElement('canvas')\n    const ctx = canvas.getContext('2d')\n    if (!ctx) {\n      reject(new Error('cannot get canvas context'))\n      return\n    }\n    const img = new Image()\n    const objectUrl = URL.createObjectURL(file)\n    img.onload = () => {\n      // 释放 object URL","sourceCodeStart":1,"sourceCodeEnd":26,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/renderer/packages/pic_utils.ts#L1-L26","documentation":"Thrown by getImageBase64AndResize() when file.type does not start with 'image/', i.e. the MIME type does not identify an image. It is an early guard before canvas-based resize/conversion runs, so non-image files never reach the rendering pipeline.","triggerScenarios":"Passing a File whose .type is not an image MIME (e.g. application/pdf, text/plain, or an empty type). The guard `if (!file.type.startsWith('image/')) throw ...` fires immediately.","commonSituations":"Attachment pipeline routes a non-image file into image processing; file.type is empty because the OS/browser could not sniff it (some SVGs/raw files); user picks a file with a renamed extension that doesn't match its real content.","solutions":["Ensure only image files (PNG/JPEG/GIF/WebP/SVG with correct MIME) are sent to this function.","If file.type is empty, set/normalize the MIME type from the extension before calling.","Route non-image files to their appropriate handler (e.g. PDF parser) instead."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"function isImageFile(file: File): boolean {\n  return file.type.startsWith('image/')\n}\nif (!isImageFile(file)) {\n  // reject or route elsewhere; do not call getImageBase64AndResize\n}","typeGuard":"function isImageFile(file: File): file is File {\n  return file.type.startsWith('image/')\n}","tryCatchPattern":"try {\n  await getImageBase64AndResize(file)\n} catch (e) {\n  if (e instanceof Error && e.message === 'file is not an image') {\n    // tell user to pick an image file\n  }\n}","preventionTips":["Filter the file picker to image MIME types.","Normalize file.type from extension when the OS leaves it empty.","Dispatch by content-type before choosing image vs document parsing."],"tags":["image","validation","file-type","vision"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}