bytedance/deer-flow · error · HTTPException

Browser automation is not enabled

Error message

Browser automation is not enabled

What it means

404 from the browser navigate route (browser.py:88) when _browser_tools_enabled() returns false. That helper (browser.py:43) checks whether the 'browser_navigate' tool is enabled in config.yaml; the live browser HTTP/WS endpoints are an opt-in surface — having Playwright importable is explicitly NOT sufficient, otherwise server-side browser control would be exposed without operator consent.

Source

Thrown at backend/app/gateway/routers/browser.py:88

    record = await thread_store.get(thread_id, user_id=user_id)
    return record is not None and record.get("user_id") == user_id


@router.post(
    "/threads/{thread_id}/browser/navigate",
    response_model=BrowserNavigateResponse,
    summary="Navigate The Live Browser Session",
    description="Steer the thread's live browser session to a URL from the UI and capture a screenshot.",
)
@require_permission("threads", "write", owner_check=True, require_existing=True)
async def navigate_browser(thread_id: ThreadId, body: BrowserNavigateRequest, request: Request) -> BrowserNavigateResponse:
    user_id = str(request.state.auth.user.id)
    thread_store = getattr(request.app.state, "thread_store", None)
    if thread_store is None or not await _browser_thread_owned_by(thread_store, thread_id, user_id):
        raise HTTPException(status_code=404, detail=f"Thread {thread_id} not found")

    if not _browser_tools_enabled():
        raise HTTPException(status_code=404, detail="Browser automation is not enabled")

    try:
        from deerflow.community.browser_automation import navigate_and_capture, redact_browser_url
    except ImportError as exc:  # Playwright is an optional dependency.
        raise HTTPException(status_code=501, detail="Browser automation is not available") from exc

    url = body.url.strip()
    if not url:
        raise HTTPException(status_code=400, detail="URL is required")

    outputs_path = get_paths().sandbox_outputs_dir(thread_id, user_id=get_effective_user_id())
    try:
        result = await navigate_and_capture(thread_id=thread_id, url=url, outputs_path=outputs_path)
    except ValueError as exc:
        # SSRF / URL validation failure.
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    except Exception as exc:
        logger.error(

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Enable the browser_navigate tool in config.yaml (tools section) and restart the Gateway
  2. Verify via the feature-availability endpoint the frontend uses (GET /api/features reports browser_control gating) and gate the UI on it so the control is not shown when disabled
  3. Do not try to bypass the check — it is an intentional operator opt-in security boundary

Example fix

# config.yaml (before) — browser tool not enabled
tools:
  enabled:
    - web_search

# after
tools:
  enabled:
    - web_search
    - browser_navigate
Defensive patterns

Strategy: validation

Validate before calling

# Gate the UI control on the feature flag before calling
const features = await fetch("/api/features").then(r => r.json());
if (features.browser_control?.enabled) showBrowserControls();

Type guard

const browserEnabled = (f: Features): boolean => Boolean(f?.browser_control?.enabled);

Try / catch

try { await navigateBrowser(threadId, url) } catch (e) { if (e.status === 404 && e.detail === "Browser automation is not enabled") hideBrowserControls(); else throw e; }

Prevention

When it happens

Trigger: POST /api/threads/{id}/browser/navigate on a deployment where the browser_navigate tool is not enabled in config.yaml (default off), including fresh installs that never opted in.

Common situations: New install without enabling browser tooling; config.yaml regenerated from the example (which leaves the tool off) after previously enabling it; feature flagged off in production but UI from a dev build still shows browser controls.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/11c0393fecad6469. Report an issue: GitHub.