{"record":{"id":"fdf9011446b391f8","repo":"tinyhumansai/openhuman","slug":"privacy-failed-to-load-capability-catalog","errorCode":null,"errorMessage":"[privacy] failed to load capability catalog:","messagePattern":"\\[privacy\\] failed to load capability catalog:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/components/settings/panels/PrivacyPanel.tsx","lineNumber":75,"sourceCode":"  const [capabilities, setCapabilities] = useState<AnnotatedCapability[]>([]);\n  const [loadState, setLoadState] = useState<'loading' | 'ready' | 'error'>('loading');\n\n  useEffect(() => {\n    let cancelled = false;\n    log('[privacy] fetching capability catalog');\n    listCapabilities()\n      .then(items => {\n        if (cancelled) return;\n        const annotated = items.filter(\n          (c): c is AnnotatedCapability => c.privacy !== undefined && c.privacy !== null\n        );\n        log('[privacy] catalog ready', { total: items.length, annotated: annotated.length });\n        setCapabilities(annotated);\n        setLoadState('ready');\n      })\n      .catch(err => {\n        if (cancelled) return;\n        console.warn('[privacy] failed to load capability catalog:', err);\n        setLoadState('error');\n      });\n    return () => {\n      cancelled = true;\n    };\n  }, []);\n\n  const handleToggleAnalytics = async () => {\n    const newValue = !analyticsEnabled;\n    try {\n      await setAnalyticsEnabled(newValue);\n    } catch (error) {\n      console.warn('[privacy] failed to persist analytics setting:', error);\n    }\n  };\n\n  const handleToggleMeetAutoHandoff = async () => {\n    const newValue = !meetAutoHandoff;","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/app/src/components/settings/panels/PrivacyPanel.tsx#L57-L93","documentation":"The Privacy panel's initial fetch of the capability catalog (listCapabilities) rejected, so the annotated-capability list could not be rendered. The panel switches loadState to 'error' (rendering an error state instead of the list) and the cancelled flag guards against a late rejection after unmount. Causes: core RPC unreachable, auth expired, or the capabilities controller erroring.","triggerScenarios":"Thrown at app/src/components/settings/panels/PrivacyPanel.tsx:75 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Check the warned error — SessionExpired means re-auth is needed before the catalog loads","Confirm the core process is healthy (Settings diagnostics or core log)","Remount/reopen the Privacy panel to re-trigger the useEffect fetch once the cause is fixed","If loadState stays 'error', inspect the core-side capabilities controller log for the failure"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}