stablyai/orca · error · Error
result.message
Error message
result.message
What it means
Thrown by assertRegisteredRepo (github.ts:181) when validateRegisteredRepo returns a 'denied' result. The thrown message is result.message, which can be one of three: 'Access denied: unknown repository path' (no registered repo matches the path/id), 'Access denied: repository path does not match repo id' (id found but path differs), or 'Access denied: GitHub source host does not match repository host' (sourceContext.hostId differs from the repo's execution host). The 'result.message' label is a static placeholder; the actual string is one of these.
Source
Thrown at src/main/ipc/github.ts:184
}
if (
typeof args !== 'string' &&
args.sourceContext?.provider === 'github' &&
args.sourceContext.hostId !== getRepoExecutionHostId(repo)
) {
return {
kind: 'denied',
reason: 'host-mismatch',
message: 'Access denied: GitHub source host does not match repository host'
}
}
return { kind: 'ok', repo }
}
function assertRegisteredRepo(args: string | RepoScopedArgs, store: Store): Repo {
const result = validateRegisteredRepo(args, store)
if (result.kind === 'denied') {
throw new Error(result.message)
}
return result.repo
}
function repoConnectionId(repo: Repo): string | null {
return repo.connectionId ?? null
}
function localGitOptionArgs(store: Store, repo: Repo): [] | [{ wslDistro?: string }] {
const localGitOptions = getLocalProjectWorktreeGitOptions(store, repo)
return Object.keys(localGitOptions).length > 0 ? [localGitOptions] : []
}
function applyRepoToPRRefreshCandidate(
store: Store,
repo: Repo,
candidate: GitHubPRRefreshCandidate
): GitHubPRRefreshCandidate {View on GitHub (pinned to 1136503c6a)
Solutions
- Re-register the repository so its path/id is in the store, then retry the GitHub IPC call.
- If repoId was supplied, drop it and retry by path only, or look up the correct id for the current path.
- For host-mismatch, ensure sourceContext.hostId matches the repo's execution host (getRepoExecutionHostId) — do not replay a task captured on host A against a repo on host B.
- Sanitize persisted task/PR references to drop repoId and connectionId when the source host changes.
Example fix
// before
assertRegisteredRepo({ repoPath: savedPath, repoId: savedId, sourceContext }, store)
// after — reconcile before asserting
const match = store.getRepos().find((r) => r.id === savedId && resolve(r.path) === resolve(savedPath))
?? store.getRepos().find((r) => resolve(r.path) === resolve(savedPath))
if (!match) throw new Error('repo not registered; re-add it')
assertRegisteredRepo({ repoPath: match.path, repoId: match.id, sourceContext: undefined }, store) Defensive patterns
Strategy: validation
Validate before calling
// Before any GitHub IPC call: verify the repo is registered and id/path agree
import { resolve } from 'node:path'
function resolveRegisteredRepoRef(store, { repoPath, repoId, sourceContext }) {
const byId = repoId ? store.getRepo(repoId) : undefined
const byPath = store.getRepos().find((r) => resolve(r.path) === resolve(repoPath))
const repo = byId && byPath && byId.id === byPath.id ? byId : byPath
if (!repo) return { kind: 'unregistered' }
if (sourceContext?.provider === 'github' && sourceContext.hostId !== getRepoExecutionHostId(repo)) {
return { kind: 'host-mismatch' }
}
return { kind: 'ok', repo }
} Type guard
export function isRegisteredRepoArgs(
args: unknown
): args is { repoPath: string; repoId?: string | null; sourceContext?: { provider?: string; hostId?: string } | null } {
return typeof args === 'object' && args !== null && typeof (args as any).repoPath === 'string'
} Try / catch
try {
await ipcRenderer.invoke('gh:something', { repoPath, repoId, sourceContext })
} catch (e) {
const msg = e instanceof Error ? e.message : ''
if (msg.startsWith('Access denied: unknown repository')) { promptReRegister(repoPath); return }
if (msg.startsWith('Access denied: repository path does not match')) { refreshRepoId(repoPath); return }
if (msg.startsWith('Access denied: GitHub source host')) { promptHostRetarget(); return }
throw e
} Prevention
- Never persist repoId across host/repo re-registration; re-resolve it by path before reuse.
- Strip sourceContext (or align hostId) when intentionally retargeting a task to a different host.
- Register repos at canonical resolved paths so symlink drift does not break lookup.
- Validate id/path/host consistency at the call site before dispatching GitHub IPC.
When it happens
Trigger: A GitHub IPC handler calls assertRegisteredRepo(args, store) where args is { repoPath, repoId?, sourceContext? }. Denied when: (a) no registered repo matches repoPath (or repoId); (b) repoId is set but the matched repo's path differs from repoPath; (c) sourceContext.provider === 'github' and sourceContext.hostId !== getRepoExecutionHostId(repo).
Common situations: Repo was unregistered or moved after a task/PR reference was captured; a task fetched on one machine is replayed on another with a same-path but different-host repo; stale repoId persisted after re-adding a repo; cross-host task sharing without host reconciliation.
Related errors
- Access denied: unknown repository path
- Access denied: unknown repository
- Access denied: unknown repository path
- Access denied: GitLab source host does not match repository
- Pull request fetch remote must not start with "-".
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/55336440ef4d9cdf.
Report an issue: GitHub.