stablyai/orca · error · Error

Could not read the selected file.

Error message

Could not read the selected file.

What it means

Thrown by the pet:import handler when fs.promises.stat(src) rejects — the selected path could not be stat'd by the main process. classifyFile already accepted the extension by this point, so the failure is a filesystem/permission problem, not a format problem. Any thrown error from stat (ENOENT, EACCES, EPERM, EIO) collapses into this single user-facing message.

Source

Thrown at src/main/ipc/pet.ts:199

        }
      ]
    }
    const result = senderWindow
      ? await dialog.showOpenDialog(senderWindow, options)
      : await dialog.showOpenDialog(options)
    if (result.canceled || result.filePaths.length === 0) {
      return null
    }
    const src = result.filePaths[0]
    const classified = classifyFile(src)
    if (!classified) {
      throw new Error('Unsupported file. Pick a PNG, APNG, JPG, GIF, WebP, or SVG.')
    }
    let srcStat: Awaited<ReturnType<typeof stat>>
    try {
      srcStat = await stat(src)
    } catch {
      throw new Error('Could not read the selected file.')
    }
    if (!srcStat.isFile()) {
      throw new Error('Selected path is not a file')
    }
    if (srcStat.size > MAX_BYTES) {
      throw new Error(
        `File is too large (${(srcStat.size / (1024 * 1024)).toFixed(1)} MB). Max is ${MAX_BYTES / (1024 * 1024)} MB.`
      )
    }

    const dir = getPetsDir()
    await mkdir(dir, { recursive: true })
    const id = randomUUID()
    // Why: keep the original extension in the on-disk name so pet:read can rebuild the Blob MIME without a separate lookup.
    const fileName = `${id}${classified.ext}`
    const dest = join(dir, fileName)
    try {
      await copyFile(src, dest)

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Re-run the import after confirming the file still exists at the picked path.
  2. If the file is on an external/network mount, copy it to local disk first, then import the local copy.
  3. Check filesystem permissions — the Electron main process must have read access to the path.
  4. For cloud-evicted files, force the sync client to download the file locally before importing.
Defensive patterns

Strategy: try-catch

Validate before calling

import { stat } from 'node:fs/promises'

async function isReadableFile(path: string): Promise<boolean> {
  try {
    const s = await stat(path)
    return s.isFile()
  } catch {
    return false
  }
}

if (!(await isReadableFile(pickedPath))) {
  notify('That file is not readable. Pick another.')
  return
}

Try / catch

try {
  await ipcRenderer.invoke('pet:import')
} catch (e) {
  if (e instanceof Error && e.message === 'Could not read the selected file.') {
    notify('The file could not be read. It may have moved or be on a disconnected drive.')
  } else throw e
}

Prevention

When it happens

Trigger: The file was deleted between the dialog pick and the stat call, the file lives on a network/external mount that became unavailable, the main process lacks read permission (EACCES/EPERM), or the path is on a removable device that was ejected mid-flow.

Common situations: User selected a file on a USB drive then unplugged it, a cloud-synced folder (iCloud/OneDrive) evicted the file to cold storage, or a permissions change between pick and import.

Related errors


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