{"record":{"id":"573577868c889e6b","repo":"stablyai/orca","slug":"waiting-for-desktop-573577","errorCode":null,"errorMessage":"Waiting for desktop...","messagePattern":"Waiting for desktop\\.\\.\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"mobile/src/source-control/use-mobile-git-requests.ts","lineNumber":23,"sourceCode":"  isMobileGitUnavailable,\n  type MobileGitStatusResult,\n  type MobileGitUpstreamStatus\n} from './mobile-git-status'\nimport type { GitCommitResult, GitRequestError } from './mobile-source-control-screen-state'\n\ntype Params = {\n  client: RpcClient | null\n  connState: ConnectionState\n  worktreeId: string\n}\n\n// The raw RPC layer for source-control git actions. Pure transport — owns no\n// screen state, so it stays out of the giant state hook.\nexport function useMobileGitRequests({ client, connState, worktreeId }: Params) {\n  const sendGitRequest = useCallback(\n    async <T>(method: string, params?: Record<string, unknown>): Promise<T> => {\n      if (!client || connState !== 'connected') {\n        throw new Error('Waiting for desktop...')\n      }\n      const response = await client.sendRequest(method, {\n        worktree: `id:${worktreeId}`,\n        ...params\n      })\n      if (!response.ok) {\n        const error = new Error(\n          response.error?.message || 'Source control action failed'\n        ) as GitRequestError\n        error.code = response.error?.code\n        throw error\n      }\n      return (response as RpcSuccess).result as T\n    },\n    [client, connState, worktreeId]\n  )\n\n  const sendCommitRequest = useCallback(","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/mobile/src/source-control/use-mobile-git-requests.ts#L5-L41","documentation":"Guard inside `sendGitRequest`, the shared transport used by every mobile source-control git RPC. If `client` is null or `connState` is anything other than `'connected'`, the request never leaves the device and this error is thrown synchronously. It signals 'not ready yet' rather than a real failure — the desktop pairing/relay is still handshaking or has dropped.","triggerScenarios":"Any code path that calls `sendGitRequest` (commit, fetch, pull, push, status, upstreamStatus, rebaseFromBase) while `connState` is `connecting|handshaking|disconnected|reconnecting|auth-failed`, or before the `client` reference is bound.","commonSituations":"User taps a source-control action immediately on screen open before the relay finishes handshaking; the connection dropped and a stale callback fires; switching hosts leaves a transient window where `client` is null.","solutions":["Gate source-control actions behind the `connected` state in the UI (disable buttons until connected).","Retry the action once `connState` reports `connected`.","If it persists, check the connection log for an `auth-failed` or `reconnecting` loop and re-pair."],"exampleFix":"// before — calling git actions regardless of connection\nawait sendGitRequest('git.commit', { message })\n\n// after — guard the call site\nif (connState !== 'connected' || !client) return\nawait sendGitRequest('git.commit', { message })","handlingStrategy":"validation","validationCode":"// Guard at the call site before any git RPC.\nfunction canSendGitRequest(client: RpcClient | null, connState: ConnectionState): boolean {\n  return client !== null && connState === 'connected'\n}\n\nif (!canSendGitRequest(client, connState)) {\n  setActionError('Waiting for desktop...')\n  return\n}","typeGuard":null,"tryCatchPattern":"// Treat 'Waiting for desktop...' as a transient, retryable condition — not a hard error.\ntry {\n  await sendGitRequest('git.status')\n} catch (err) {\n  if (err instanceof Error && err.message === 'Waiting for desktop...') {\n    // wait for connection, then retry\n  } else throw err\n}","preventionTips":["Disable source-control actions in the UI until connState === 'connected'.","Never assume the client is non-null after a host switch — re-check.","Distinguish this transient guard from real RPC failures in the UI."],"tags":["connection","rpc","transport","guard"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}