Skip to content

fix(browser): floor browser-use CLI subprocess PATH with sane system dirs - #93116

Closed
justcarlosm wants to merge 1 commit into
NousResearch:mainfrom
justcarlosm:fix/browser-use-subprocess-path-floor
Closed

justcarlosm wants to merge 1 commit into
NousResearch:mainfrom
justcarlosm:fix/browser-use-subprocess-path-floor

Conversation

@justcarlosm

Copy link
Copy Markdown
Contributor

Fixes #93115

Summary

browser_exec dies with exit 127 (realpath: not found … exec: /python: not found) whenever a Hermes process inherits a PATH of only version-manager dirs — observed in the wild from kanban/cron profile workers carrying one nvm dir repeated 7x. The uv-installed browser-use entry point is a POSIX sh trampoline that resolves dirname/realpath through PATH at invocation time, so it fails before its own Python starts.

The agent-browser backend already defends against exactly this hazard via tools/browser_tool.py::_merge_browser_path(); this change gives the browser-use backend the same floor.

What changed

  • tools/browser_use_cli.py
    • _base_subprocess_env() now floors the child PATH through a new _floor_subprocess_path() helper.
    • The helper delegates to browser_tool._merge_browser_path() (same sane-dir list, never drops or reorders existing entries) and degrades to appending FHS bin dirs if that import is ever unavailable.
    • Windows is a no-op — .cmd shims don't trampoline through PATH.
    • PYTHONPATH/PYTHONHOME stripping (browser_exec crashes: pydantic_core ModuleNotFoundError when PYTHONPATH points at Hermes venv (desktop app) #83427 family) was the previous env-hygiene layer here; this is the same class of hazard, PATH flavor.
  • tests/tools/test_browser_use_cli.py
    • test_subprocess_env_floors_version_manager_only_path — the observed-in-the-wild case (nvm-only ×7) must yield /usr/bin + /bin.
    • test_floor_preserves_existing_entries_and_order — floor only adds; existing entries keep relative order.
    • test_floor_survives_missing_sibling_helper — degraded fallback still guarantees /usr/bin.

Test plan

  • pytest tests/tools/test_browser_use_cli.py -o 'addopts=' -q → 95 passed
  • Neighbors green: test_browser_use_session_expiry.py, test_browser_homebrew_paths.py → 32 passed
  • Real-subprocess E2E against upstream HEAD: worker process started with env -i HOME=… PATH=<nvm-dir>_find_cli() resolves the managed uvx path → _base_subprocess_env() child PATH contains /usr/binuvx browser-use --version exits 0 printing 0.1.9; control run without the floor reproduces exit 127 byte-for-byte with the field report.

Notes for reviewers

  • The floor deliberately reuses _merge_browser_path() rather than duplicating its list — if the sane-dir set changes for agent-browser, browser-use follows. The try/except keeps this file independent of that module's internals in tests (existing pattern in this suite stubs tools.browser_tool).
  • Scope is one spawn seam (_base_subprocess_env) — every browser-use CLI launch goes through it, including the uvx zero-install fallback resolved by _find_cli().

…dirs

Profile-spawned workers (kanban bots, cron jobs) can inherit a PATH of
only version-manager dirs — observed in the wild as one nvm node dir
repeated 7x. The uv-installed browser-use binary is a POSIX sh
trampoline that resolves dirname/realpath through PATH, so it died
with 'realpath: not found … exec: /python: not found' (exit 127)
before its own Python ever started.

_base_subprocess_env now floors the child PATH via browser_tool's
_merge_browser_path (the agent-browser backend already guards the same
hazard), degrading to appending FHS bin dirs if that import is ever
unavailable. Windows is a no-op (.cmd shims don't trampoline).

Verified: unit tests + real uvx browser-use --version under a
nvm-only-PATH worker env, rc 127 -> rc 0.
@alt-glitch alt-glitch added type/bug Something isn't working tool/browser Browser automation (CDP, Playwright) P2 Medium — degraded but workaround exists labels Aug 23, 2026
@Enough1122

Copy link
Copy Markdown
Contributor

AI code review — automated review for reference, author can ignore or act on any point.

Good diagnosis and a sensible guard: flooring the subprocess PATH so coreutils (dirname/realpath in the uv trampoline) stay reachable fixes a real class of profile-worker breakage, and reusing browser_tool._merge_browser_path avoids inventing a second dir list. Tests cover the main paths well. A few points:

  1. tools/browser_use_cli.py:149-151 — the bare except Exception: pass swallows everything from the import and the call to _merge_browser_path, including genuine bugs inside that helper (a TypeError would silently degrade to the FHS fallback). Narrow to except ImportError (or ModuleNotFoundError) and add a debug log on fallback so drift between the two implementations is observable.

  2. tools/browser_use_cli.py:96-97 — on Windows the function returns path unchanged even when it's empty or unset. The documented hazard is POSIX-specific, but a PATH-less env will fail differently on Windows too; either floor with %SystemRoot%\System32 equivalents or state the Windows no-op rationale in a comment at this exact spot (it's currently only in the docstring).

  3. Test gap: there's no case for PATH being entirely absent (env.pop("PATH") before calling _base_subprocess_env()), asserting the floor still appends /usr/bin etc. Given the incident this PR responds to was "PATH of only nvm dirs", the fully-missing case is the natural neighbor — cheap to add.

Minor: the hardcoded FHS list duplicates browser_tool's; consider exporting one shared constant so they can't diverge.

@teknium1

Copy link
Copy Markdown
Collaborator

Merged via #93356 (rebase) — your commit is on main with authorship preserved.

@teknium1 teknium1 closed this Aug 24, 2026
@justcarlosm
justcarlosm deleted the fix/browser-use-subprocess-path-floor branch August 24, 2026 04:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Medium — degraded but workaround exists tool/browser Browser automation (CDP, Playwright) type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: browser-use CLI dies with 'realpath: not found' (exit 127) when profile workers inherit a version-manager-only PATH

4 participants