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

  1. Re-register the repository so its path/id is in the store, then retry the GitHub IPC call.
  2. If repoId was supplied, drop it and retry by path only, or look up the correct id for the current path.
  3. 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.
  4. 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

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


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