stablyai/orca · error · Error

Access denied: unknown repository path

Error message

Access denied: unknown repository path

What it means

Thrown by assertRegisteredRepo in hosted-review.ts:31 on the path-only branch: no repoId was supplied and no registered repo's resolved path matches resolve(repoPath). This is the hosted-review filesystem-auth boundary for the path-only lookup, mirroring the github.ts/gitlab.ts guards.

Source

Thrown at src/main/ipc/hosted-review.ts:34

import { createStackedHostedReview } from '../source-control/stacked-hosted-review-creation'
import { getHostedReviewForBranch } from '../source-control/hosted-review'
import { resolveRegisteredWorktreePath } from './filesystem-auth'
import { listRepoWorktrees } from '../repo-worktrees'
import { getLocalProjectWorktreeGitOptions } from '../project-runtime-git-options'
import { getWorktreeSharedLinkPaths } from '../git/worktree-shared-directories'

function assertRegisteredRepo(repoPath: string, store: Store, repoId?: string): Repo {
  if (repoId) {
    const repo = store.getRepo(repoId)
    if (!repo || repo.path !== repoPath) {
      throw new Error('Access denied: unknown repository')
    }
    return repo
  }
  const resolvedRepoPath = resolve(repoPath)
  const repo = store.getRepos().find((r) => resolve(r.path) === resolvedRepoPath)
  if (!repo) {
    throw new Error('Access denied: unknown repository path')
  }
  return repo
}

async function resolveHostedReviewWorktreePath(
  repo: Repo,
  store: Store,
  worktreePath?: string
): Promise<string> {
  if (!worktreePath) {
    return repo.path
  }
  if (repo.connectionId) {
    const remoteWorktreePath = normalizeRemoteHostedReviewPath(worktreePath)
    const repoWorktrees = await listRepoWorktrees(repo)
    if (
      !repoWorktrees.some(
        (worktree) => normalizeRemoteHostedReviewPath(worktree.path) === remoteWorktreePath

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Register the repository at the exact path (use the canonical resolved form), then retry the hosted-review operation.
  2. If repoPath is a symlink, register the real path so resolve() aligns.
  3. Drop stale hosted-review references keyed at unregistered paths.
  4. Pre-check the path is registered before dispatching the IPC call.

Example fix

// before
assertRegisteredRepo(repoPath, store)

// after — confirm registration shape first
if (!store.getRepos().some((r) => resolve(r.path) === resolve(repoPath))) {
  throw new Error(`re-register repo at ${repoPath} before retrying`)
}
assertRegisteredRepo(repoPath, store)
Defensive patterns

Strategy: validation

Validate before calling

// Before a hosted-review IPC call keyed by path only: confirm registration
import { resolve } from 'node:path'

function isHostedReviewRepoRegistered(store, repoPath) {
  const resolved = resolve(repoPath)
  return store.getRepos().some((r) => resolve(r.path) === resolved)
}

Type guard

export function isHostedReviewPathRef(args: unknown): args is { repoPath: string } {
  return typeof args === 'object' && args !== null && typeof (args as any).repoPath === 'string'
}

Try / catch

try {
  await ipcRenderer.invoke('hostedReview:something', { repoPath })
} catch (e) {
  if (e instanceof Error && e.message === 'Access denied: unknown repository path') {
    promptReRegister(repoPath); return
  }
  throw e
}

Prevention

When it happens

Trigger: A hosted-review IPC handler calls assertRegisteredRepo(repoPath, store) with no repoId, and resolve(repoPath) matches none of store.getRepos(). The path was never registered or no longer matches.

Common situations: Repo unregistered before a hosted-review operation; repoPath is a symlink/relative form that resolve() normalizes away from the registered path; repo moved; cross-host replay where the repo lives on another machine.

Understand the failure class

Related errors


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