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

  1. Wrap the component tree in <ActiveBackendProvider> in tests or ensure the route layout includes it.
  2. 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.
  3. 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

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


AI-assisted analysis of OpenHands/OpenHands@500b4c533e (2026-08-12). Data as JSON: /api/errors/aa7d7b6b8396b5a5. Report an issue: GitHub.