stablyai/orca · error · Error
Access denied: GitLab source host does not match repository
Error message
Access denied: GitLab source host does not match repository host
What it means
Thrown by assertRegisteredRepo in gitlab.ts:87 when the repo IS registered but the source-context host check fails: args.sourceContext.provider === 'gitlab' and args.sourceContext.hostId !== getRepoExecutionHostId(repo). This prevents a task fetched from one execution host from mutating a same-path repo on a different host.
Source
Thrown at src/main/ipc/gitlab.ts:93
}
const resolvedRepoPath = resolve(args.repoPath)
return store.getRepos().find((r) => resolve(r.path) === resolvedRepoPath)
}
// Why: mirror github.ts assertRegisteredRepo — main-process handlers
// must never operate on a path the user hasn't explicitly registered as
// a repo (filesystem-auth boundary). Source context adds a host check so a
// task fetched from one machine cannot mutate a same-path repo on another.
function assertRegisteredRepo(args: GitLabRepoSelectorArgs, store: Store): Repo {
const repo = findRegisteredGitLabRepo(args, store)
if (!repo) {
throw new Error('Access denied: unknown repository path')
}
if (
args.sourceContext?.provider === 'gitlab' &&
args.sourceContext.hostId !== getRepoExecutionHostId(repo)
) {
throw new Error('Access denied: GitLab source host does not match repository host')
}
return repo
}
function repoConnectionId(repo: Repo): string | null {
return repo.connectionId ?? null
}
function localGitOptionArgs(store: Store, repo: Repo): [] | [LocalGitExecOptions] {
const localGitOptions = getLocalProjectWorktreeGitOptions(store, repo)
return localGitOptions.wslDistro ? [{ wslDistro: localGitOptions.wslDistro }] : []
}
function hostedReviewOptionArgs(store: Store, repo: Repo): [] | [HostedReviewExecutionOptions] {
const localGitOptions = getLocalProjectWorktreeGitOptions(store, repo)
return localGitOptions.wslDistro
? [{ localGitExecOptions: { wslDistro: localGitOptions.wslDistro } }]
: []View on GitHub (pinned to 1136503c6a)
Solutions
- Run the GitLab operation against the repo on the host recorded in sourceContext.hostId (the originating host).
- If the host genuinely changed, update the repo's execution host association and refresh sourceContext.hostId to match getRepoExecutionHostId(repo).
- Strip sourceContext when intentionally retargeting a task to a different host (do so only with explicit user intent).
- Validate that the active connection/host matches the task's source host before dispatching the GitLab IPC call.
Example fix
// before
assertRegisteredRepo({ repoPath, sourceContext: { provider: 'gitlab', hostId: taskHostId } }, store)
// after — only dispatch when host matches the registered repo's execution host
const repo = findRegisteredGitLabRepo({ repoPath }, store)
if (getRepoExecutionHostId(repo) !== taskHostId) {
throw new Error(`retarget to host ${getRepoExecutionHostId(repo)} or drop sourceContext`)
}
assertRegisteredRepo({ repoPath, sourceContext: { provider: 'gitlab', hostId: taskHostId } }, store) Defensive patterns
Strategy: validation
Validate before calling
// Before a GitLab IPC call carrying sourceContext: confirm host alignment
import { getRepoExecutionHostId } from '../../shared/execution-host'
function gitLabHostMatches(store, args) {
const repo = store.getRepos().find((r) => resolve(r.path) === resolve(args.repoPath))
if (!repo) return { kind: 'unregistered' }
if (args.sourceContext?.provider === 'gitlab' && args.sourceContext.hostId !== getRepoExecutionHostId(repo)) {
return { kind: 'host-mismatch', expected: getRepoExecutionHostId(repo), got: args.sourceContext.hostId }
}
return { kind: 'ok' }
} Type guard
export function hasGitLabSourceContext(
args: unknown
): args is { repoPath: string; sourceContext: { provider: 'gitlab'; hostId: string } } {
return (
typeof args === 'object' && args !== null &&
(args as any).sourceContext?.provider === 'gitlab' &&
typeof (args as any).sourceContext?.hostId === 'string'
)
} Try / catch
try {
await ipcRenderer.invoke('gl:something', { repoPath, sourceContext })
} catch (e) {
if (e instanceof Error && e.message === 'Access denied: GitLab source host does not match repository host') {
promptHostRetarget(sourceContext.hostId); return
}
throw e
} Prevention
- Run GitLab operations on the host recorded in sourceContext.hostId; do not replay cross-host.
- When the execution host genuinely changes, update the repo association and refresh sourceContext.hostId.
- Strip sourceContext only when intentionally retargeting (explicit user intent).
- Validate host alignment at the call site before dispatching GitLab IPC.
When it happens
Trigger: A GitLab operation carries sourceContext = { provider: 'gitlab', hostId: H1 } but the matched repo's execution host is H2 (different SSH target / different machine). The path matches a registered repo, but it belongs to a different host than the one the task originated from.
Common situations: Same repo path exists on two machines (e.g. both have ~/code/app); a GitLab task captured on host A is replayed on host B; SSH target changed/reconnected under a new hostId; stale sourceContext persisted across a host reconfiguration.
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
- Access denied: unknown repository path
- Access denied: worktree does not belong to repository
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/6566ba621867512c.
Report an issue: GitHub.