{"record":{"id":"aa7d7b6b8396b5a5","repo":"OpenHands/OpenHands","slug":"useactivebackendcontext-must-be-used-inside-activ","errorCode":null,"errorMessage":"useActiveBackendContext must be used inside <ActiveBackendProvider>","messagePattern":"useActiveBackendContext must be used inside <ActiveBackendProvider>","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/contexts/active-backend-context.tsx","lineNumber":228,"sourceCode":"      setActive,\n      addBackend,\n      updateBackend,\n      removeBackend,\n    }),\n    [snapshot, setActive, addBackend, updateBackend, removeBackend],\n  );\n\n  return (\n    <ActiveBackendContext.Provider value={value}>\n      {children}\n    </ActiveBackendContext.Provider>\n  );\n}\n\nexport function useActiveBackendContext(): ActiveBackendContextValue {\n  const ctx = React.useContext(ActiveBackendContext);\n  if (!ctx) {\n    throw new Error(\n      \"useActiveBackendContext must be used inside <ActiveBackendProvider>\",\n    );\n  }\n  return ctx;\n}\n\n/**\n * Read the resolved active backend.\n *\n * Falls back to a synthesized env-derived local backend when called\n * outside an `<ActiveBackendProvider>` (e.g. from a unit test that\n * mounts a narrow component without the full provider stack). That\n * synthesized backend is identical to the seed used on first install.\n *\n * Components that need to mutate state (`setActive`, `addBackend`,\n * etc.) must use `useActiveBackendContext()` directly — that throws if\n * the provider is missing, since mutation requires the live store.\n */","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/OpenHands/OpenHands/blob/500b4c533e9393e44cb92894bcbb18438ef473b6/src/contexts/active-backend-context.tsx#L210-L246","documentation":"Thrown by useActiveBackendContext() in src/contexts/active-backend-context.tsx when React.useContext() returns null, meaning the calling component was rendered without an <ActiveBackendProvider> ancestor. This hook is the mutating variant (setActive, addBackend, etc.) and requires the live store. A read-only fallback useActiveBackend() exists that synthesizes a default backend outside the provider.","triggerScenarios":"A component calling useActiveBackendContext() (the mutating API) is rendered in a unit test without <ActiveBackendProvider>; a component is mounted in an isolated environment (storybook, test) that lacks the full provider stack; tree restructuring removed the provider.","commonSituations":"Unit test renders a backend-management component (e.g. BackendSelector, ManageBackendsModal) without wrapping in <ActiveBackendProvider>; refactoring moves the provider below a component that needs it.","solutions":["Wrap the component tree in <ActiveBackendProvider> in tests or ensure the route layout includes it.","If only reading the active backend (no mutation needed), use useActiveBackend() instead — it falls back to a synthesized env-derived local backend when outside the provider.","Use the project's test-utils renderWithProviders helper which includes the provider stack."],"exampleFix":"// before — mutating hook used where only a read is needed\nconst { active } = useActiveBackendContext();\n// after — read-only hook with safe fallback\nconst { active } = useActiveBackend();","handlingStrategy":"type-guard","validationCode":"// For read-only access outside the provider, use the fallback hook\nimport { useActiveBackend } from \"#/contexts/active-backend-context\";\nconst { active } = useActiveBackend(); // synthesizes a default if no provider\n\n// Only use useActiveBackendContext() when you need mutation AND know the provider is mounted","typeGuard":"import React from \"react\";\nimport { ActiveBackendContext } from \"#/contexts/active-backend-context\";\n\nfunction useOptionalActiveBackendContext() {\n  return React.useContext(ActiveBackendContext); // null if no provider\n}\n\nconst ctx = useOptionalActiveBackendContext();\nif (!ctx) {\n  // fall back to read-only useActiveBackend() or return early\n}","tryCatchPattern":null,"preventionTips":["Prefer useActiveBackend() (read-only, safe fallback) over useActiveBackendContext() (mutating, throws).","Wrap backend-management components in <ActiveBackendProvider> in tests.","Use renderWithProviders() from test-utils.tsx which includes the provider stack."],"tags":["react","context","backend","provider"],"backgroundTag":null,"analyzedSha":"500b4c533e9393e44cb92894bcbb18438ef473b6","analyzedAt":"2026-08-12T10:07:46.034Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}