different-ai/openwork · error

Failed to load providers (${response.status}).

Error message

Failed to load providers (${response.status}).

What it means

loadProviders, inside the useOrgLlmProviders hook, GETs /v1/llm-providers?scope=...; a non-ok response throws an Error preferring the server message with the status embedded. React state (setLlmProviders) is only updated after this check, so failed loads keep prior state and surface the error to the caller.

Source

Thrown at ee/apps/den-web/app/(den)/dashboard/_components/llm-provider-data.tsx:524

  const scope = options.scope ?? "manageable";

  async function loadProviders() {
    if (!orgId) {
      setLlmProviders([]);
      setError("Organization not found.");
      return;
    }

    setBusy(true);
    setError(null);
    try {
      const { response, payload } = await requestJson(
        `/v1/llm-providers?scope=${encodeURIComponent(scope)}`,
        { method: "GET" },
        15000,
      );
      if (!response.ok) {
        throw new Error(getErrorMessage(payload, `Failed to load providers (${response.status}).`));
      }

      const nextProviders = isRecord(payload) && Array.isArray(payload.llmProviders)
        ? payload.llmProviders.map(asLlmProvider).filter((entry): entry is DenLlmProvider => entry !== null)
        : [];
      setLlmProviders(nextProviders);
    } catch (loadError) {
      setError(loadError instanceof Error ? loadError.message : "Failed to load the provider library.");
    } finally {
      setBusy(false);
    }
  }

  useEffect(() => {
    void loadProviders();
  }, [orgId, scope]);

  return {

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Inspect response.status and the server message to classify the failure (auth vs permission vs route vs server).
  2. For 401, refresh the session or redirect to sign-in; for 403, verify the user's org role.
  3. For 404, align frontend and backend deployments.
  4. Validate the `scope` value passed to useOrgLlmProviders against the API's accepted values.
  5. Check den-api logs for 5xx root causes and retry after recovery.

Example fix

// before
throw new Error(getErrorMessage(payload, `Failed to load providers (${response.status}).`));
// after
if (response.status === 403) throw new Error("You do not have permission to view providers for this organization.");
throw new Error(getErrorMessage(payload, `Failed to load providers (${response.status}).`));
Defensive patterns

Strategy: try-catch

Validate before calling

const VALID_SCOPES = ["org", "user"] as const;
// guard before the query runs
if (!(VALID_SCOPES as readonly string[]).includes(scope)) throw new Error(`Invalid provider scope: ${scope}`);

Type guard

function isProviderScope(v: string): v is "org" | "user" {
  return v === "org" || v === "user";
}

Try / catch

const { error } = useOrgLlmProviders(scope);
if (error) {
  const msg = error instanceof Error ? error.message : String(error);
  if (/\((401|403)\)/.test(msg)) handleAuthOrPermission(msg);
  else setProviderLoadError(msg);
}

Prevention

When it happens

Trigger: GET /v1/llm-providers returns 401 (expired session), 403 (insufficient org role), 404 (route/server version mismatch), 429, or 5xx; an invalid scope value causing a 400 from the server.

Common situations: Session expiring while the providers panel is mounted; user without admin permissions viewing org providers; frontend deployed against an older den-api without this endpoint; malformed scope argument passed into the hook.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/a6ca1bcfbee3ffb6. Report an issue: GitHub.