NousResearch/hermes-agent · error · Error

Could not read image

Error message

Could not read image

What it means

Thrown by copyImageFromUrl after resourceBufferFromUrl succeeded but nativeImage.createFromBuffer(buffer) produced an empty image (isEmpty()). Electron's nativeImage only decodes PNG/JPEG and a few formats; unsupported formats (e.g. AVIF, WebP on older Electron, SVG) or corrupt bytes yield an empty native image rather than a throw.

Source

Thrown at apps/desktop/electron/main.ts:4730

      res.on('data', chunk => chunks.push(chunk))
      res.on('end', () => {
        resolve({
          buffer: Buffer.concat(chunks),
          mimeType: res.headers['content-type'] || 'application/octet-stream'
        })
      })
    })

    req.on('error', reject)
  })
}

async function copyImageFromUrl(rawUrl) {
  const { buffer } = (await resourceBufferFromUrl(rawUrl)) as any
  const image = nativeImage.createFromBuffer(buffer)

  if (image.isEmpty()) {
    throw new Error('Could not read image')
  }

  clipboard.writeImage(image)
}

async function saveImageFromUrl(rawUrl) {
  const { buffer, mimeType } = (await resourceBufferFromUrl(rawUrl)) as any
  const fallbackName = filenameFromUrl(rawUrl, `image${extensionForMimeType(mimeType) || '.png'}`)

  const result = await dialog.showSaveDialog(mainWindow, {
    title: 'Save Image',
    defaultPath: fallbackName
  })

  if (result.canceled || !result.filePath) {
    return false
  }

View on GitHub (pinned to c896c09c42)

Solutions

  1. Convert the image to PNG/JPEG before copying (e.g. decode in the renderer with createImageBitmap + canvas, then hand the PNG bytes to the clipboard path).
  2. If the source is SVG, rasterize it first — nativeImage cannot represent vector images.
  3. Verify the buffer bytes start with a known magic number (PNG \x89PNG, JPEG \xff\xd8) before calling.

Example fix

// before
const image = nativeImage.createFromBuffer(buffer)
if (image.isEmpty()) throw new Error('Could not read image')

// after — check magic bytes to distinguish 'unsupported codec' from 'not an image'
const isPng = buffer[0] === 0x89 && buffer[1] === 0x50
const isJpeg = buffer[0] === 0xff && buffer[1] === 0xd8
if (!isPng && !isJpeg) {
  throw new Error('Could not read image (only PNG/JPEG are supported by nativeImage)')
}
const image = nativeImage.createFromBuffer(buffer)
Defensive patterns

Strategy: try-catch

Validate before calling

function isDecodableImageBuffer(buf) {
  if (!(buf && buf.length > 8)) return false
  const isPng = buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4e && buf[3] === 0x47
  const isJpeg = buf[0] === 0xff && buf[1] === 0xd8
  return isPng || isJpeg
}

Try / catch

try {
  await copyImageFromUrl(url)
} catch (e) {
  if (/Could not read image/.test(e.message)) {
    await copyAsPngViaRenderer(url) // rasterize in renderer, then clipboard.writeImage
  } else throw e
}

Prevention

When it happens

Trigger: Copying an image whose bytes decoded fine but whose codec nativeImage can't parse; a buffer that is valid data but not an image at all; truncated download producing undecodable bytes.

Common situations: Modern web formats (WebP/AVIF) on Electron builds without codec support; SVG 'images'; partially downloaded files over flaky networks.

Related errors


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/c87e5ee3254f60d9. Report an issue: GitHub.