stablyai/orca · warning · Error

Repo icon image must be 256KB or smaller.

Error message

Repo icon image must be 256KB or smaller.

What it means

Thrown by shell:pickRepoIcon when the selected PNG's file size exceeds MAX_REPO_ICON_UPLOAD_BYTES (256 * 1024 = 262144 bytes, defined in src/shared/repo-icon.ts). The size is measured by fs.stat on the real file, so compression claims in metadata do not matter — only the on-disk byte count.

Source

Thrown at src/main/ipc/shell.ts:274

    async (): Promise<{ dataUrl: string; fileName: string } | null> => {
      const result = await dialog.showOpenDialog({
        properties: ['openFile'],
        filters: [{ name: 'Repo icon images', extensions: ['png'] }]
      })
      if (result.canceled || result.filePaths.length === 0) {
        return null
      }

      const filePath = result.filePaths[0]
      const extension = extname(filePath).toLowerCase()
      const mimeType = REPO_ICON_IMAGE_MIME_TYPES[extension]
      if (!mimeType) {
        throw new Error('Repo icons must be PNG files.')
      }

      const stats = await stat(filePath)
      if (stats.size > MAX_REPO_ICON_UPLOAD_BYTES) {
        throw new Error('Repo icon image must be 256KB or smaller.')
      }

      const buffer = await readFile(filePath)
      return {
        dataUrl: `data:${mimeType};base64,${buffer.toString('base64')}`,
        fileName: basename(filePath)
      }
    }
  )

  ipcMain.handle('shell:pickAudio', async (): Promise<string | null> => {
    const result = await dialog.showOpenDialog({
      properties: ['openFile'],
      filters: [{ name: 'Audio', extensions: ['ogg', 'mp3', 'wav', 'm4a', 'aac', 'flac'] }]
    })
    if (result.canceled || result.filePaths.length === 0) {
      return null
    }

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Downscale the PNG to 256x256 or 512x512 and re-export.
  2. Compress/quantize the PNG (pngquant, oxipng, or 'magick -strip -define') to reduce bytes.
  3. Check the file size in the renderer after selection and warn before sending.
  4. If the icon must be detailed, crop tightly to remove transparent padding.

Example fix

// before (icon.png is 400KB)
await ipc.invoke('shell:pickRepoIcon')

// after
// reduce: pngquant --quality=70-90 --output icon-sm.png icon.png
//   or: magick icon.png -resize 256x256 icon-256.png
await ipc.invoke('shell:pickRepoIcon') // now selects the smaller file
Defensive patterns

Strategy: validation

Validate before calling

import { MAX_REPO_ICON_UPLOAD_BYTES } from '@shared/repo-icon'
import { stat } from 'fs/promises'

async function ensureIconUnderLimit(filePath: string): Promise<boolean> {
  const { size } = await stat(filePath)
  return size <= MAX_REPO_ICON_UPLOAD_BYTES // 256 * 1024
}

if (!(await ensureIconUnderLimit(picked))) {
  showError('Repo icon image must be 256KB or smaller.')
  return
}

Type guard

async function iconWithinSizeLimit(filePath: string, limit: number): Promise<boolean> {
  try {
    const { size } = await stat(filePath)
    return size <= limit
  } catch {
    return false
  }
}

Try / catch

try {
  await ipc.invoke('shell:pickRepoIcon')
} catch (e) {
  if (/256KB|smaller/i.test((e as Error).message)) showError('Shrink the PNG to 256KB or less.')
  else throw e
}

Prevention

When it happens

Trigger: Selecting a high-resolution PNG (e.g. 1024x1024 or larger) or an uncompressed PNG whose bytes exceed 256KB. The MIME check (1297) passes because it is a real PNG, but the size guard then fails.

Common situations: Large brand logos exported at print resolution; uncompressed PNG screenshots; icons with alpha channels and fine detail that inflate size; users unaware of the 256KB ceiling.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/09a50e8c1bc5af83. Report an issue: GitHub.