{"record":{"id":"09a50e8c1bc5af83","repo":"stablyai/orca","slug":"repo-icon-image-must-be-256kb-or-smaller","errorCode":null,"errorMessage":"Repo icon image must be 256KB or smaller.","messagePattern":"Repo icon image must be 256KB or smaller\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/main/ipc/shell.ts","lineNumber":274,"sourceCode":"    async (): Promise<{ dataUrl: string; fileName: string } | null> => {\n      const result = await dialog.showOpenDialog({\n        properties: ['openFile'],\n        filters: [{ name: 'Repo icon images', extensions: ['png'] }]\n      })\n      if (result.canceled || result.filePaths.length === 0) {\n        return null\n      }\n\n      const filePath = result.filePaths[0]\n      const extension = extname(filePath).toLowerCase()\n      const mimeType = REPO_ICON_IMAGE_MIME_TYPES[extension]\n      if (!mimeType) {\n        throw new Error('Repo icons must be PNG files.')\n      }\n\n      const stats = await stat(filePath)\n      if (stats.size > MAX_REPO_ICON_UPLOAD_BYTES) {\n        throw new Error('Repo icon image must be 256KB or smaller.')\n      }\n\n      const buffer = await readFile(filePath)\n      return {\n        dataUrl: `data:${mimeType};base64,${buffer.toString('base64')}`,\n        fileName: basename(filePath)\n      }\n    }\n  )\n\n  ipcMain.handle('shell:pickAudio', async (): Promise<string | null> => {\n    const result = await dialog.showOpenDialog({\n      properties: ['openFile'],\n      filters: [{ name: 'Audio', extensions: ['ogg', 'mp3', 'wav', 'm4a', 'aac', 'flac'] }]\n    })\n    if (result.canceled || result.filePaths.length === 0) {\n      return null\n    }","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/shell.ts#L256-L292","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Downscale the PNG to 256x256 or 512x512 and re-export.","Compress/quantize the PNG (pngquant, oxipng, or 'magick -strip -define') to reduce bytes.","Check the file size in the renderer after selection and warn before sending.","If the icon must be detailed, crop tightly to remove transparent padding."],"exampleFix":"// before (icon.png is 400KB)\nawait ipc.invoke('shell:pickRepoIcon')\n\n// after\n// reduce: pngquant --quality=70-90 --output icon-sm.png icon.png\n//   or: magick icon.png -resize 256x256 icon-256.png\nawait ipc.invoke('shell:pickRepoIcon') // now selects the smaller file","handlingStrategy":"validation","validationCode":"import { MAX_REPO_ICON_UPLOAD_BYTES } from '@shared/repo-icon'\nimport { stat } from 'fs/promises'\n\nasync function ensureIconUnderLimit(filePath: string): Promise<boolean> {\n  const { size } = await stat(filePath)\n  return size <= MAX_REPO_ICON_UPLOAD_BYTES // 256 * 1024\n}\n\nif (!(await ensureIconUnderLimit(picked))) {\n  showError('Repo icon image must be 256KB or smaller.')\n  return\n}","typeGuard":"async function iconWithinSizeLimit(filePath: string, limit: number): Promise<boolean> {\n  try {\n    const { size } = await stat(filePath)\n    return size <= limit\n  } catch {\n    return false\n  }\n}","tryCatchPattern":"try {\n  await ipc.invoke('shell:pickRepoIcon')\n} catch (e) {\n  if (/256KB|smaller/i.test((e as Error).message)) showError('Shrink the PNG to 256KB or less.')\n  else throw e\n}","preventionTips":["Downscale icons to 256x256 or 512x512 before upload.","Compress with pngquant/oxipng to reduce byte size.","Check file size client-side after selection."],"tags":["ipc","shell","repo-icon","validation","size-limit"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}