{"record":{"id":"2b2969f9db8c99c1","repo":"stablyai/orca","slug":"unable-to-load-agent-sessions","errorCode":null,"errorMessage":"Unable to load agent sessions","messagePattern":"Unable to load agent sessions","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mobile/src/agent-history/use-mobile-agent-history-state.ts","lineNumber":126,"sourceCode":"        // proceed even if the worktree isn't found, to avoid a stuck spinner.\n        if (options.scope !== 'all' && !activeWorktree && !worktreesLoaded) {\n          if (isCurrent()) {\n            setScreenState((prev) => (prev.kind === 'ready' ? prev : { kind: 'loading' }))\n          }\n          return\n        }\n\n        const scopePaths = deriveMobileAiVaultScopePaths(options.scope, activeWorktree, worktrees)\n        const response = await client.sendRequest('aiVault.listSessions', {\n          limit: MOBILE_AI_VAULT_SESSION_LIMIT,\n          force: options.force,\n          scopePaths\n        })\n        if (!isCurrent()) {\n          return\n        }\n        if (!response.ok) {\n          throw new Error(response.error?.message || 'Unable to load agent sessions')\n        }\n        const result = (response as RpcSuccess).result as AiVaultListResult\n        setScreenState({ kind: 'ready', sessions: result.sessions, issues: result.issues })\n      } catch (err) {\n        if (!isCurrent()) {\n          return\n        }\n        const message = err instanceof Error ? err.message : 'Unable to load agent sessions'\n        setHostStatusResult(null)\n        setScreenState({ kind: 'error', message })\n      }\n    },\n    [activeWorktree, client, connState, worktrees, worktreesLoaded]\n  )\n\n  // Initial + reconnect load. Why: scope switches reuse the host's 15s cache\n  // (force:false) so a tab tap is cheap; only an explicit refresh bypasses it.\n  useEffect(() => {","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/mobile/src/agent-history/use-mobile-agent-history-state.ts#L108-L144","documentation":"Thrown by the mobile agent-history hook after it has confirmed capabilities and computed scopePaths, when the actual `aiVault.listSessions` RPC returns ok=false. It is the data-fetch failure for the session list itself; the generic string is used only when the host's error.message is empty.","triggerScenarios":"aiVault.listSessions returns a failure (host-side filesystem error reading the vault directory, permission denied, scopePaths resolve to a missing path, or a timeout). The catch wraps it and sets screen state to 'error'.","commonSituations":"The AI vault directory is missing or unreadable on the host, scopePaths point at a worktree that no longer exists, the host's vault indexing hit an exception, or the request exceeded its timeout under heavy load.","solutions":["Check the host logs for the aiVault.listSessions handler's error.","Confirm the scopePaths/worktree still exists on the host (worktree was not deleted).","Retry with options.force=true to bypass a stale cache that may have poisoned state.","Ensure the vault directory permissions allow the host process to read."],"exampleFix":"// before\nif (!response.ok) {\n  throw new Error(response.error?.message || 'Unable to load agent sessions')\n}\n\n// after — surface the host error code for actionable retries\nif (!response.ok) {\n  const code = (response as RpcFailure).error.code\n  if (code === 'scopeNotFound') { setScreenState({ kind: 'empty' }); return }\n  throw new Error((response as RpcFailure).error.message || 'Unable to load agent sessions')\n}","handlingStrategy":"try-catch","validationCode":"// Ensure scopePaths are non-empty before the fetch\nconst scopePaths = deriveMobileAiVaultScopePaths(options.scope, activeWorktree, worktrees)\nif (options.scope !== 'all' && scopePaths.length === 0) {\n  setScreenState({ kind: 'empty' }); return\n}","typeGuard":"function isListSessionsSuccess(r: RpcSuccess | RpcFailure): r is RpcSuccess & { result: AiVaultListResult } {\n  return r.ok\n}","tryCatchPattern":"try {\n  const response = await client.sendRequest('aiVault.listSessions', { limit, force, scopePaths })\n  if (!isCurrent()) return\n  if (!response.ok) throw new Error(response.error?.message || 'Unable to load agent sessions')\n} catch (err) {\n  if (!isCurrent()) return\n  setScreenState({ kind: 'error', message: (err as Error).message })\n}","preventionTips":["Confirm the worktree still exists before scoping the fetch.","Retry with force=true to bypass stale cache after host-side changes.","Map known host error codes to dedicated screen states instead of generic error."],"tags":["mobile","rpc","ai-vault","session-history","fallback-message"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}