stablyai/orca · error · Error

Managed Claude auth child file is not owned by Orca.

Error message

Managed Claude auth child file is not owned by Orca.

What it means

Thrown by writeClaudeManagedAuthFile() when the target child file (.credentials.json or oauth-account.json) exists but isOwnedChildFile() returns false — i.e. the file's canonical path (realpath) does not lie under the managed auth directory, or it is a symlink, or it is not a regular file. This is a path-traversal / ownership guard: Orca only overwrites files it created inside its own managed account directory.

Source

Thrown at src/main/claude-accounts/managed-auth-path.ts:81

  const filePath = resolve(managedAuthPath, filename)
  try {
    if (!isOwnedChildFile(managedAuthPath, filePath)) {
      return null
    }
    return readFileSync(filePath, 'utf-8')
  } catch {
    return null
  }
}

export function writeClaudeManagedAuthFile(
  managedAuthPath: string,
  filename: '.credentials.json' | 'oauth-account.json',
  contents: string
): void {
  const filePath = resolve(managedAuthPath, filename)
  if (existsSync(filePath) && !isOwnedChildFile(managedAuthPath, filePath)) {
    throw new Error('Managed Claude auth child file is not owned by Orca.')
  }
  writeFileAtomically(filePath, contents, { mode: 0o600 })
}

function isManagedAuthMarkerValid(markerPath: string, accountId: string): boolean {
  try {
    if (
      !existsSync(markerPath) ||
      lstatSync(markerPath).isSymbolicLink() ||
      !lstatSync(markerPath).isFile()
    ) {
      return false
    }
    return readFileSync(markerPath, 'utf-8').trim() === accountId
  } catch {
    return false
  }
}

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Remove the offending file/symlink and let Orca recreate it: delete the child file then re-run the auth write.
  2. Confirm managedAuthPath resolves under app.getPath('userData')/claude-accounts and was created via resolveOwnedClaudeManagedAuthPath.
  3. Audit for symlinks in the account auth directory (lstat) and reject/repair before write.
  4. Re-add the Claude account so Orca recreates a clean owned directory.
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync, lstatSync } from 'node:fs'

function isSafeOwnedChild(parentDir: string, file: string): boolean {
  if (!existsSync(file)) return true // new file is fine
  const stat = lstatSync(file)
  return stat.isFile() && !stat.isSymbolicLink()
}

Try / catch

try {
  writeClaudeManagedAuthFile(managedAuthPath, '.credentials.json', contents)
} catch (error) {
  if (error instanceof Error && /not owned by Orca/.test(error.message)) {
    // Recreate the account directory or remove the offending file
    throw new Error('Auth file is foreign; re-add the account.')
  }
  throw error
}

Prevention

When it happens

Trigger: The target file path resolves (via symlink) outside the managedAuthPath. A pre-existing .credentials.json was created by an unrelated process. Someone replaced the file with a symlink. The managed directory was moved/relabeled so realpath no longer matches.

Common situations: User manually placed a .credentials.json in the managed dir. A symlink attack or misconfigured managedAuthPath pointing at a shared location. Stale account directory after a userData migration changed canonical paths.

Related errors


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