stablyai/orca · warning · Error
Repo icons must be PNG files.
Error message
Repo icons must be PNG files.
What it means
Thrown by the shell:pickRepoIcon handler when the chosen file's extension is not in REPO_ICON_IMAGE_MIME_TYPES, which currently contains only '.png' -> 'image/png'. The dialog filter suggests PNG, but the actual file is double-checked by extension to its lowercase MIME; a jpg, gif, webp, or any non-png file is rejected.
Source
Thrown at src/main/ipc/shell.ts:269
return result.filePaths[0]
})
ipcMain.handle(
'shell:pickRepoIconImage',
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'],View on GitHub (pinned to 1136503c6a)
Solutions
- Convert the image to PNG before selecting it (any image editor or 'magick input.jpg output.png').
- If SVG is desired, rasterize it to PNG at the intended size first.
- In the renderer, filter the dialog strictly to PNG and validate the extension client-side before relying on the result.
- Show an inline hint that only PNG is accepted next to the icon picker.
Example fix
// before (user picks icon.jpg)
await ipc.invoke('shell:pickRepoIcon')
// after
// convert first: magick icon.jpg icon.png
await ipc.invoke('shell:pickRepoIcon') // now selects icon.png
// renderer-side guard:
const result = await ipc.invoke('shell:pickRepoIcon')
// (handler already enforces; surface its error as 'Please choose a PNG file.') Defensive patterns
Strategy: validation
Validate before calling
import { extname } from 'path'
function isPngFile(filePath: string): boolean {
return extname(filePath).toLowerCase() === '.png'
}
const picked = await pickFile()
if (picked && !isPngFile(picked)) {
showError('Repo icons must be PNG files.')
return
}
await ipc.invoke('shell:pickRepoIcon') Type guard
import { extname } from 'path'
function isRepoIconPng(filePath: unknown): filePath is string {
return typeof filePath === 'string' && extname(filePath).toLowerCase() === '.png'
} Try / catch
try {
await ipc.invoke('shell:pickRepoIcon')
} catch (e) {
if (/PNG/.test((e as Error).message)) showError('Please choose a PNG file.')
else throw e
} Prevention
- Convert icons to PNG before selection.
- Filter the dialog to PNG and re-validate the extension client-side.
- Show an 'PNG only' hint next to the icon picker.
When it happens
Trigger: User selects a JPG, GIF, WEBP, SVG, or extensionless file in the picker. Even if the OS dialog shows only PNGs, on some platforms the filter is not enforced, so a user can pick another type. The extension lookup fails and the error is thrown before reading the file.
Common situations: Users with icons exported as JPG/SVG; renamed files whose content does not match the extension; OS dialog filter bypassed via drag path; users attempting to upload a logo in a non-PNG format.
Related errors
- Repo icon image must be 256KB or smaller.
- Selected file is not a markdown document.
- ${label} is required
- ${label} is required
- Cannot download to a directory
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/7ddf5f87a777e0ce.
Report an issue: GitHub.