stablyai/orca · error · Error

Permission denied: unable to create '${name}'

Error message

Permission denied: unable to create '${name}'

What it means

Thrown by rethrowWithUserMessage() when the createFile write fails with errno code EACCES or EPERM. These codes mean the process lacks permission to create/write the target (or to traverse its parent directory). The message names basename(targetPath) so the renderer can surface a friendly 'Permission denied' notice.

Source

Thrown at src/main/ipc/filesystem-mutations.ts:40

import { importExternalPathsSsh } from './filesystem-import-ssh'
import type { SshMutationExpectation } from '../../shared/ssh-types'
import { assertSshMutationExpectation } from '../ssh/ssh-connection-generation'
import { renameLocalPathSerializedByDestination } from '../destination-serialized-local-rename'

/**
 * Re-throw filesystem errors with user-friendly messages.
 * The `wx` flag on writeFile throws a raw EEXIST with no helpful message,
 * so we catch it here and provide context the renderer can display directly.
 */
function rethrowWithUserMessage(error: unknown, targetPath: string): never {
  const name = basename(targetPath)
  if (error instanceof Error && 'code' in error) {
    const code = (error as NodeJS.ErrnoException).code
    if (code === 'EEXIST') {
      throw new Error(`A file or folder named '${name}' already exists in this location`)
    }
    if (code === 'EACCES' || code === 'EPERM') {
      throw new Error(`Permission denied: unable to create '${name}'`)
    }
  }
  throw error
}

/**
 * Ensure `targetPath` does not already exist. Throws if it does.
 *
 * Note: this is a non-atomic check — a concurrent operation could create the
 * path between `lstat` and the caller's next action. Acceptable for a desktop
 * app with low concurrency; `createFile` uses the `wx` flag for an atomic
 * alternative where possible.
 */
async function assertNotExists(targetPath: string): Promise<void> {
  try {
    await lstat(targetPath)
    throw new Error(
      `A file or folder named '${basename(targetPath)}' already exists in this location`

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Create the file in a writable location (move the workspace or target dir onto a writable volume).
  2. Fix permissions on the parent directory so the Orca process can write (chmod/chown).
  3. Remount the network volume read-write, or with the correct user mapping.
  4. Remove the immutable flag on the target if set (chflags/chattr).
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the parent dir is writable by this process before createFile
import { access, constants } from 'node:fs/promises'
import { dirname } from 'node:path'
async function parentIsWritable(p: string): Promise<boolean> {
  try { await access(dirname(p), constants.W_OK); return true } catch { return false }
}

Try / catch

try {
  await window.api.fs.createFile({ filePath })
} catch (e) {
  if (e instanceof Error && /Permission denied/.test(e.message)) {
    // pick a writable location or fix parent permissions, then retry
  } else throw e
}

Prevention

When it happens

Trigger: fs:createFile is invoked for a path whose parent directory is not writable by the Orca process, or where an existing same-named entry is not replaceable (and 'wx' surfaces EACCES/EPERM), or on a read-only/protected filesystem.

Common situations: Workspace root inside a system/protected directory (e.g. /usr, a read-only mount); file flagged immutable; parent directory owned by another user with no write bit; SMB/NFS mount mounted read-only or with wrong uid.

Related errors


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