{"record":{"id":"c7a36a6d87520976","repo":"Hmbown/CodeWhale","slug":"unrecognized-raster-format-file","errorCode":null,"errorMessage":"unrecognized raster format: ${file}","messagePattern":"unrecognized raster format: (.+?)","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/backends/darwin.mjs","lineNumber":42,"sourceCode":" * CODEWHALE_CU_MAX_IMAGE_BYTES in mcp/server.mjs, which keeps the hard guard.\n */\nconst rasterByteBudget = () => (Number(process.env.CODEWHALE_CU_MAX_IMAGE_BYTES) > 0\n  ? Number(process.env.CODEWHALE_CU_MAX_IMAGE_BYTES)\n  : 5_000_000);\n\n/**\n * Pixel dimensions from a PNG IHDR or a JPEG frame header, reading only the\n * bytes that carry them rather than the whole raster.\n */\nfunction imagePixels(file) {\n  const fd = fs.openSync(file, \"r\");\n  try {\n    const head = Buffer.alloc(24);\n    fs.readSync(fd, head, 0, 24, 0);\n    if (head[0] === 0x89 && head.toString(\"ascii\", 1, 4) === \"PNG\") {\n      return { w: head.readUInt32BE(16), h: head.readUInt32BE(20) };\n    }\n    if (head[0] !== 0xff || head[1] !== 0xd8) throw new ExecError(`unrecognized raster format: ${file}`);\n    // Walk JPEG segments to the frame header. SOF0/1/2/3/5..7/9..11/13..15\n    // carry the dimensions; DHT/DQT and the rest are skipped by their length.\n    const size = fs.fstatSync(fd).size;\n    const seg = Buffer.alloc(9);\n    for (let at = 2; at + 9 <= size; ) {\n      fs.readSync(fd, seg, 0, 9, at);\n      if (seg[0] !== 0xff) throw new ExecError(`malformed JPEG at byte ${at}: ${file}`);\n      const marker = seg[1];\n      if (marker >= 0xc0 && marker <= 0xcf && marker !== 0xc4 && marker !== 0xc8 && marker !== 0xcc) {\n        return { w: seg.readUInt16BE(7), h: seg.readUInt16BE(5) };\n      }\n      if (marker === 0xd8 || (marker >= 0xd0 && marker <= 0xd9)) { at += 2; continue; }\n      at += 2 + seg.readUInt16BE(2);\n    }\n    throw new ExecError(`JPEG carries no frame header: ${file}`);\n  } finally {\n    fs.closeSync(fd);\n  }","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/backends/darwin.mjs#L24-L60","documentation":"`imagePixels` in the darwin backend sniffs the first bytes of a screenshot file to read image dimensions. It recognizes PNG (0x89 'PNG') and JPEG (0xFF 0xD8) magic numbers; anything else raises `unrecognized raster format: <file>`. It only reads the header, so it supports exactly these two formats.","triggerScenarios":"Calling imagePixels (screenshot dimension lookup) on a file that is not PNG or JPEG — e.g. a TIFF screenshot from an older macOS capture path, a WebP/HEIC image, an empty file, or a text/HTML placeholder written where an image was expected.","commonSituations":"macOS screencapture configured for a different format (screencapture -t tiff), a truncated or zero-byte file whose header is unreadable, or a path pointing at the wrong file.","solutions":["Ensure the capture pipeline writes PNG (default) or JPEG, e.g. `screencapture -t png <file>`.","Verify the file exists and is non-empty before calling imagePixels.","Convert other formats to PNG/JPEG before dimension lookup.","Check the path — the file may be an HTML error page or placeholder, not the screenshot."],"exampleFix":"// before\\nexec(\"screencapture -t tiff /tmp/shot.tif\");\\nimagePixels(\"/tmp/shot.tif\"); // throws\\n// after\\nexec(\"screencapture -t png /tmp/shot.png\");\\nimagePixels(\"/tmp/shot.png\");","handlingStrategy":"fallback","validationCode":"const fd = fs.openSync(file, \"r\");\\nconst head = Buffer.alloc(2); fs.readSync(fd, head, 0, 2, 0); fs.closeSync(fd);\\nconst isPng = head[0] === 0x89, isJpeg = head[0] === 0xff && head[1] === 0xd8;\\nif (!isPng && !isJpeg) throw new Error(`${file} is not PNG/JPEG`);","typeGuard":"const isSupportedRaster = (buf) => buf[0] === 0x89 || (buf[0] === 0xff && buf[1] === 0xd8);","tryCatchPattern":"try { return imagePixels(file); } catch (e) { if (/unrecognized raster format/.test(e.message)) return dimsViaSips(file); throw e; }","preventionTips":["Always capture with screencapture's default png format.","Stat the file and check size > 0 before parsing.","Convert non-PNG/JPEG screenshots with sips before dimension lookup."],"tags":["image","file-format","darwin","screenshot"],"backgroundTag":"unsupported-operation","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}