stablyai/orca · error · Error

Cannot download to a directory

Error message

Cannot download to a directory

What it means

Thrown by inspectDownloadDestination when the user-selected save path already exists and is a directory. The function stats the destination before download begins; if it is a directory, the download cannot proceed because overwriting a directory with a file would be destructive or impossible.

Source

Thrown at src/main/ipc/filesystem.ts:244

const DOWNLOAD_SESSION_TTL_MS = 30 * 60 * 1000

function createSiblingTransferPath(destinationPath: string, suffix: string): string {
  // Why: promotion renames must stay on the destination volume, so transfer paths remain siblings.
  return join(dirname(destinationPath), `.${randomUUID()}.${suffix}`)
}

async function cleanupLocalTransferPath(filePath: string | null): Promise<void> {
  if (!filePath) {
    return
  }
  await rm(filePath, { force: true }).catch(() => {})
}

async function inspectDownloadDestination(destinationPath: string): Promise<{ existed: boolean }> {
  try {
    const destinationStat = await stat(destinationPath)
    if (destinationStat.isDirectory()) {
      throw new Error('Cannot download to a directory')
    }
    return { existed: true }
  } catch (error) {
    if (isENOENT(error)) {
      return { existed: false }
    }
    throw error
  }
}

async function assertDestinationStillUnclaimed(destinationPath: string): Promise<void> {
  try {
    await stat(destinationPath)
  } catch (error) {
    if (isENOENT(error)) {
      return
    }
    throw error

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Choose a different filename in the save dialog that does not match an existing directory.
  2. Rename or remove the conflicting directory before saving.
  3. In the renderer, check the save path after the dialog returns and warn the user if it is a directory.

Example fix

// before: user selects /downloads/myproject (an existing folder) as save target
// after: user picks a file path
//   /downloads/myproject.txt or /downloads/myproject-export.json
Defensive patterns

Strategy: validation

Validate before calling

const { stat } = await import('node:fs/promises')

async function assertDownloadTargetIsNotDirectory(destinationPath: string): Promise<void> {
  try {
    const st = await stat(destinationPath)
    if (st.isDirectory()) {
      throw new Error(`${destinationPath} is a directory — choose a file path`)
    }
  } catch (error: any) {
    if (error.code === 'ENOENT') return // path is free
    throw error
  }
}

Try / catch

try {
  await ipcRenderer.invoke('fs:saveDownloadedFile', args)
} catch (error) {
  if (error instanceof Error && error.message === 'Cannot download to a directory') {
    showUserError('The chosen path is a directory. Select a file name.')
    return
  }
  throw error
}

Prevention

When it happens

Trigger: In the fs:saveDownloadedFile or fs:downloadFile flow, the user picks a save path in the dialog that points to an existing directory. The stat on that path returns isDirectory() true.

Common situations: The user types a name in the save dialog that matches an existing folder name. The user selects an existing directory entry from the file browser. The defaultPath suggestion collides with a directory already in the target folder.

Related errors


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