OpenHands/OpenHands · error · NoBackendAvailableError

No backend is configured.

Error message

No backend is configured.

What it means

NoBackendAvailableError thrown inside the localAutomationAxios request interceptor when getEffectiveLocalBackend() returns null. This interceptor runs on every automation-service axios call that doesn't have an explicit baseURL pinned (import/cleanup calls set baseURL explicitly and skip this path). It resolves the host and session key from the backend registry on each request so edits in the Manage Backends UI are picked up dynamically.

Source

Thrown at src/api/automation-service/automation-service.api.ts:92

  const requestHeaders = await buildAutomationRequestHeaders();
  Object.entries(requestHeaders).forEach(([name, value]) => {
    config.headers.set(name, value);
  });

  // Import uses an explicit baseURL/header pair so its POST, PATCH, and
  // cleanup stay pinned to the backend selected when the mutation started.
  if (config.baseURL) return config;

  // Resolve the local backend on every call so it tracks the
  // currently-active local backend (and any host/key edits made via the
  // manage-backends UI), rather than freezing whatever value the
  // agent-server-config produced at module load time.
  // Using the backend registry (rather than the build-time VITE_SESSION_API_KEY
  // env var) ensures the published npm package picks up the runtime-injected
  // session key that scripts/static-server.mjs seeds into localStorage, fixing
  // the 401 errors reported in issue #829.
  const backend = getEffectiveLocalBackend();
  if (!backend) throw new NoBackendAvailableError();
  // eslint-disable-next-line no-param-reassign
  config.baseURL = backend.host;

  const apiKey = backend.apiKey?.trim();
  if (apiKey) {
    config.headers.set("X-Session-API-Key", apiKey);
  }
  return config;
});

function normalizeAutomationSdkVersion(version: unknown): string | null {
  if (typeof version !== "string") return null;
  const trimmed = version.trim();
  return trimmed || null;
}

function getAutomationSdkVersionFromResponse(
  response: AutomationSdkVersionResponse,

View on GitHub (pinned to 500b4c533e)

Solutions

  1. Ensure a local backend is registered before interacting with the Automation tab.
  2. Guard automation UI components with the active backend kind check — only show automation controls when getActiveBackend().backend.kind === 'local'.
  3. If automation calls must work with cloud, they already route through callCloudProxy; verify the code path isn't falling through to localAutomationAxios due to a missing kind check.

Example fix

// before: automation call without backend guard
const automations = await AutomationService.listAutomations();

// after: guard on backend kind
if (getActiveBackend().backend.kind !== 'local') return;
const automations = await AutomationService.listAutomations();
Defensive patterns

Strategy: validation

Validate before calling

import { getActiveBackend } from '#/api/backend-registry/active-store';

function canCallLocalAutomation(): boolean {
  return getActiveBackend().backend.kind === 'local';
}

// Before automation API calls:
if (!canCallLocalAutomation()) return;

Type guard

import { isNoBackendAvailableError } from '#/api/agent-server-client-options';

function isAutomationNoBackend(e: unknown): boolean {
  return isNoBackendAvailableError(e);
}

Try / catch

try {
  const data = await AutomationService.listAutomations();
} catch (error) {
  if (isNoBackendAvailableError(error)) {
    // Backend registry empty or cloud-only; hide automation UI
    return [];
  }
  throw error;
}

Prevention

When it happens

Trigger: Any AutomationService static method that uses localAutomationAxios without a pinned baseURL (listAutomations, getAutomation, updateAutomation, deleteAutomation, etc.) is invoked when no local backend is registered. The interceptor fires before the HTTP request leaves the browser.

Common situations: Automation service calls issued before the backend registry is seeded during app bootstrap; user switched to a cloud backend and the automation UI still triggers a local-path call; the backend was deleted between the automation list loading and a subsequent action.

Related errors


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