stablyai/orca · error · Error

Unable to load source control

Error message

Unable to load source control

What it means

Thrown by `loadStatus` when the `git.status` RPC fails after exhausting retries. The retry loop (up to `SELECTOR_RETRY_COUNT`) only retries `selector_not_found` and transient refresh errors (`request_aborted`/`aborting`); git-unavailable codes set an 'unavailable' screen state instead. Any other failure, or a retryable failure that never succeeds, throws this and sets the screen error state (unless `preserveReadyOnFailure` keeps the last good screen).

Source

Thrown at mobile/src/source-control/use-mobile-source-control-loaders.ts:233

            }
            if (isMobileGitUnavailable(response.error?.code, response.error?.message)) {
              setScreenState({
                kind: 'unavailable',
                message: 'Update Orca desktop to use Source Control on mobile.'
              })
              return false
            }
            const shouldRetry =
              response.error?.code === 'selector_not_found' ||
              isMobileGitTransientRefreshError(response.error?.code, response.error?.message)
            if (shouldRetry && attempt < SELECTOR_RETRY_COUNT) {
              await wait(SELECTOR_RETRY_DELAY_MS)
              if (!isCurrentLoad()) {
                return false
              }
              continue
            }
            throw new Error(response.error?.message || 'Unable to load source control')
          }
        } catch (err) {
          if (!isCurrentLoad()) {
            return false
          }
          const message = err instanceof Error ? err.message : 'Unable to load source control'
          setScreenState((prev) => {
            // Why: git mutations can succeed while the immediate status refresh
            // races a desktop abort; keep the last good screen instead of flashing
            // a full-screen error that Retry fixes a moment later.
            if (options?.preserveReadyOnFailure && prev.kind === 'ready') {
              return prev
            }
            return { kind: 'error', message }
          })
          return false
        }
        return false

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Tap Retry — a new load generation re-fetches status with a fresh selector.
  2. Confirm the worktree still exists on the host and reselect it if not.
  3. On the host, clear a stale `.git/index.lock` or run `git status` to surface the underlying error.
  4. If `selector_not_found` recurs, ensure worktree registration completed before opening source control.
Defensive patterns

Strategy: retry

Validate before calling

// Confirm the worktree selector is valid before relying on status loads.
const probe = await client.sendRequest('worktree.show', { worktree: `id:${worktreeId}` })
if (!probe.ok) { /* expect selector_not_found retries then this error */ }

Try / catch

// loadStatus already retries selector_not_found / transient errors;
// on final failure it sets screenState to error — wire a Retry button to loadStatus({ force: true }).
try {
  await loadStatus({ force: true })
} catch {
  // screen state is 'error'; user-initiated Retry recovers
}

Prevention

When it happens

Trigger: Opening/refreshing the source-control screen where `git.status` persistently returns ok:false: invalid/stale worktree selector that never resolves, a non-transient git error (corrupt index, permission denied), or `selector_not_found` that persists across all retries.

Common situations: The worktree was deleted or moved after the route opened; the host git index is locked or corrupt; SSH host lost its git binary; the selector referenced a worktree that is mid-create and not yet registered.

Related errors


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