stablyai/orca · error · Error
Access denied: unknown repository
Error message
Access denied: unknown repository
What it means
Thrown by assertRegisteredRepo in hosted-review.ts:21 on the repoId branch: store.getRepo(repoId) returns no repo, OR the returned repo's path does not equal the supplied repoPath. This guards hosted-review (PR) handlers so a repoId that is unknown or whose path disagrees with the request is rejected as 'Access denied: unknown repository'.
Source
Thrown at src/main/ipc/hosted-review.ts:27
import type { Repo } from '../../shared/types'
import type { Store } from '../persistence'
import type { StatsCollector } from '../stats/collector'
import {
createHostedReview,
getHostedReviewCreationEligibility
} from '../source-control/hosted-review-creation'
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.pathView on GitHub (pinned to 1136503c6a)
Solutions
- Re-resolve the repoId from the current store for the given path before calling (e.g. look up by path), then retry.
- If the repo was re-added, refresh persisted references to the new repoId.
- Drop the repoId and let the path-based lookup (hosted-review.ts:31) handle it when the id is untrusted.
- Validate id/path consistency at the call site before dispatching.
Example fix
// before
assertRegisteredRepo(repoPath, store, persistedRepoId)
// after — reconcile id against path before asserting
const byPath = store.getRepos().find((r) => resolve(r.path) === resolve(repoPath))
if (!byPath) throw new Error('repo not registered')
assertRegisteredRepo(repoPath, store, byPath.id) Defensive patterns
Strategy: validation
Validate before calling
// Before a hosted-review IPC call keyed by repoId: reconcile id with path
import { resolve } from 'node:path'
function reconcileRepoId(store, repoPath, repoId) {
if (!repoId) return store.getRepos().find((r) => resolve(r.path) === resolve(repoPath))?.id
const repo = store.getRepo(repoId)
return repo && resolve(repo.path) === resolve(repoPath) ? repoId : undefined
} Type guard
export function isHostedReviewRepoRef(
args: unknown
): args is { repoPath: string; repoId?: string } {
return typeof args === 'object' && args !== null && typeof (args as any).repoPath === 'string'
} Try / catch
try {
await ipcRenderer.invoke('hostedReview:something', { repoPath, repoId })
} catch (e) {
if (e instanceof Error && e.message === 'Access denied: unknown repository') {
const freshId = reconcileRepoId(store, repoPath, repoId); promptRefreshRepoId(freshId); return
}
throw e
} Prevention
- Re-resolve repoId from the current store by path before reusing a persisted id.
- After removing and re-adding a repo, refresh all persisted repoId references.
- Drop an untrusted repoId and fall back to the path-only lookup.
- Validate id/path consistency at the call site before dispatching.
When it happens
Trigger: A hosted-review IPC handler calls assertRegisteredRepo(repoPath, store, repoId) with a repoId. Denied when store.getRepo(repoId) is falsy, or when the found repo's repo.path !== repoPath. The id/path pair is inconsistent.
Common situations: Stale repoId persisted after the repo was removed and re-added (new id); repoPath drifted (moved/symlink) while repoId stayed; cross-host replay with a repoId from a different store; manually edited/corrupted repoId.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Access denied: unknown repository path
- result.message
- Access denied: unknown repository path
- Access denied: GitLab source host does not match repository
- Access denied: worktree does not belong to repository
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/79822d77f035a110.
Report an issue: GitHub.