stablyai/orca · error · Error

Could not save the pet.

Error message

Could not save the pet.

What it means

Thrown by the pet:import handler when copyFile(src, dest) rejects while copying the validated image into the userData/sidekicks/custom directory. The handler cleans up the partial destination (rm with force, errors swallowed) before rethrowing, so no half-written file is left behind. The collapsed message hides the underlying errno (ENOSPC, EACCES, EROFS, EIO).

Source

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

      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)
    } catch {
      await rm(dest, { force: true }).catch(() => {})
      throw new Error('Could not save the pet.')
    }

    const rawLabel = basename(src, extname(src)).trim()
    const label = rawLabel.length > 0 ? rawLabel.slice(0, 40) : 'Custom pet'
    return {
      id,
      label,
      fileName,
      mimeType: classified.mimeType,
      kind: 'image'
    }
  })

  ipcMain.handle('pet:importPetBundle', async (event): Promise<CustomPet | null> => {
    const senderWindow =
      BrowserWindow.fromWebContents(event.sender) ?? BrowserWindow.getFocusedWindow()
    // Why: the bundle is a folder, but Finder may let users pick `pet.json` inside it — post-pick logic walks up to the parent.
    const options: Electron.OpenDialogOptions = {

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Free disk space on the volume holding the app's userData directory and retry the import.
  2. Confirm the userData/sidekicks/custom directory is writable by the Electron process.
  3. If userData is on a network/removable volume, move it to local storage or remount and retry.
  4. On Windows, temporarily disable aggressive AV scanning of the userData folder and retry.
Defensive patterns

Strategy: try-catch

Validate before calling

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

async function hasDiskSpace(dir: string, need = 64 * 1024 * 1024): Promise<boolean> {
  try {
    const { bavail, bsize } = await statfs(dir)
    return bavail * bsize > need
  } catch {
    return true
  }
}

if (!(await hasDiskSpace(userDataDir))) {
  notify('Not enough disk space to save the pet.')
  return
}

Try / catch

try {
  await ipcRenderer.invoke('pet:import')
} catch (e) {
  if (e instanceof Error && e.message === 'Could not save the pet.') {
    notify('Saving failed. Check disk space and permissions, then try again.')
  } else throw e
}

Prevention

When it happens

Trigger: The disk holding userData is full (ENOSPC), the pets directory is read-only or permission-restricted (EACCES/EROFS), the destination volume was disconnected, or an AV/backup process locked the file on Windows.

Common situations: Low disk space on the system drive, userData redirected to a network share that dropped, sandbox/permissions tightening on macOS userData, or Windows antivirus locking the new file mid-copy.

Related errors


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