openclaw/openclaw · error · Error

Browser control is disabled

Error message

Browser control is disabled

What it means

Thrown by resolveGatewayBridge when an extension-relay Gateway upgrade arrives but Browser control cannot be obtained: getBrowserControlState() is null and startBrowserControlServiceFromConfig() also returns null. A null return means the bundled Browser plugin is effectively disabled (config browser.enabled=false, plugins.browser disabled, or resolved.enabled=false) or browser auth could not be auto-configured. This guards the WebSocket upgrade path so a connecting Chrome extension gets a deterministic failure instead of a half-bound relay.

Source

Thrown at extensions/browser/src/browser/extension-relay/gateway-relay-route.ts:69

function requestedProfileName(resource: string, fallback: string): string {
  return new URL(resource, "http://127.0.0.1").searchParams.get("profile") ?? fallback;
}

function defaultExtensionProfileName(profiles: Record<string, { driver?: string }>): string {
  for (const [name, profile] of Object.entries(profiles)) {
    if (profile.driver === "extension") {
      return name;
    }
  }
  return "chrome";
}

async function resolveGatewayBridge(resource: string) {
  let state = getBrowserControlState();
  if (!state) {
    state = await startBrowserControlServiceFromConfig();
    if (!state) {
      throw new Error("Browser control is disabled");
    }
  }
  const profileName = requestedProfileName(
    resource,
    defaultExtensionProfileName(state.resolved.profiles),
  );
  const resolved = resolveProfile(state.resolved, profileName);
  if (!resolved || resolved.driver !== "extension") {
    throw new Error(`Extension browser profile "${profileName}" was not found`);
  }
  return {
    bridge: (await ensureExtensionRelayForProfile(state, resolved)).bridge,
    profileName,
  };
}

/** Handle the plugin-owned Gateway upgrade path. */
export async function handleGatewayExtensionUpgrade(

View on GitHub (pinned to 01804a7531)

Solutions

  1. Verify openclaw.json does not set browser.enabled=false and that plugins.browser is not disabled; run `openclaw configure` or check `openclaw doctor`.
  2. Confirm the bundled browser plugin is enabled (enabledByDefault is true) and no plugins.browser.enabled=false override exists.
  3. If browser control is intentionally disabled, uninstall or disconnect the Chrome extension so it stops attempting the relay upgrade.
  4. Re-run `openclaw browser extension pair` after re-enabling to confirm the relay secret and extension handshake work end to end.

Example fix

// before (openclaw.json)
{
  "browser": { "enabled": false }
}
// after
{
  "browser": { "enabled": true }
}
Defensive patterns

Strategy: validation

Validate before calling

import { getRuntimeConfig } from '../config/config.js';
import { isDefaultBrowserPluginEnabled } from '../plugin-enabled.js';

function assertBrowserControlStartable(): void {
  const cfg = getRuntimeConfig();
  if (!isDefaultBrowserPluginEnabled(cfg)) {
    throw new Error('Browser plugin is disabled in config; cannot start Browser control');
  }
  if (cfg.browser?.enabled === false) {
    throw new Error('browser.enabled=false; cannot start Browser control');
  }
}
// Call before issuing extension-relay upgrade or local dispatch.

Try / catch

try {
  const { bridge, profileName } = await resolveGatewayBridge(resource);
  // ...
} catch (err) {
  if (err instanceof Error && err.message === 'Browser control is disabled') {
    destroy(socket, '503 Service Unavailable'); // surface to extension as transient
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Occurs during handleGatewayExtensionUpgrade (the /browser/extension WebSocket path) when: (a) openclaw.json sets browser.enabled=false; (b) plugins.browser.enabled=false; (c) the Browser plugin is disabled by normalizePluginsConfig; or (d) resolveBrowserConfig yields enabled=false. The check runs after origin and token validation succeed, inside prepareAuthenticated (v2) or the legacy resolveGatewayBridge call.

Common situations: Operators who explicitly disabled the browser plugin but still have the Chrome extension installed and attempting to connect; environments where a prior plugin was disabled via plugins config; CI/test harnesses that load a stripped config; configs where browser.enabled was set false during a security lockdown without removing the extension pairing.

Related errors


AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12). Data as JSON: /api/errors/ada76b35fe8e2273. Report an issue: GitHub.