OpenHands/OpenHands · error · Error
useActiveBackendContext must be used inside <ActiveBackendPr
Error message
useActiveBackendContext must be used inside <ActiveBackendProvider>
What it means
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.
Source
Thrown at src/contexts/active-backend-context.tsx:228
setActive,
addBackend,
updateBackend,
removeBackend,
}),
[snapshot, setActive, addBackend, updateBackend, removeBackend],
);
return (
<ActiveBackendContext.Provider value={value}>
{children}
</ActiveBackendContext.Provider>
);
}
export function useActiveBackendContext(): ActiveBackendContextValue {
const ctx = React.useContext(ActiveBackendContext);
if (!ctx) {
throw new Error(
"useActiveBackendContext must be used inside <ActiveBackendProvider>",
);
}
return ctx;
}
/**
* Read the resolved active backend.
*
* Falls back to a synthesized env-derived local backend when called
* outside an `<ActiveBackendProvider>` (e.g. from a unit test that
* mounts a narrow component without the full provider stack). That
* synthesized backend is identical to the seed used on first install.
*
* Components that need to mutate state (`setActive`, `addBackend`,
* etc.) must use `useActiveBackendContext()` directly — that throws if
* the provider is missing, since mutation requires the live store.
*/View on GitHub (pinned to 500b4c533e)
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.
Example fix
// before — mutating hook used where only a read is needed
const { active } = useActiveBackendContext();
// after — read-only hook with safe fallback
const { active } = useActiveBackend(); Defensive patterns
Strategy: type-guard
Validate before calling
// For read-only access outside the provider, use the fallback hook
import { useActiveBackend } from "#/contexts/active-backend-context";
const { active } = useActiveBackend(); // synthesizes a default if no provider
// Only use useActiveBackendContext() when you need mutation AND know the provider is mounted Type guard
import React from "react";
import { ActiveBackendContext } from "#/contexts/active-backend-context";
function useOptionalActiveBackendContext() {
return React.useContext(ActiveBackendContext); // null if no provider
}
const ctx = useOptionalActiveBackendContext();
if (!ctx) {
// fall back to read-only useActiveBackend() or return early
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- useSidebarMobileNav must be used within SidebarMobileNavProv
- useScrollContext must be used within a ScrollProvider
AI-assisted analysis of OpenHands/OpenHands@500b4c533e (2026-08-12).
Data as JSON: /api/errors/aa7d7b6b8396b5a5.
Report an issue: GitHub.