hermes - ✅(Solved) Fix [Bug]: browser_navigate crashes with TypeError: '>' not supported between instances of 'int' and 'NoneType' after hermes update [5 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#14331Fetched 2026-04-24 06:17:43
View on GitHub
Comments
0
Participants
1
Timeline
12
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×6labeled ×4referenced ×2

Error Message

ERROR tools.registry: Tool browser_navigate dispatch error: '>' not supported between instances of 'int' and 'NoneType'
Traceback (most recent call last): File "/Users/goofy/hermes-agent/tools/registry.py", line 163, in dispatch
return entry.handler(args, **kwargs)
File "/Users/goofy/hermes-agent/tools/browser_tool.py", line 2310, in <lambda> handler=lambda args, **kw: browser_navigate(url=args.get("url", ""), task_id=kw.get("task_id")), File "/Users/goofy/hermes-agent/tools/browser_tool.py", line 1333, in browser_navigate result = _run_browser_command(effective_task_id, "open", [url], timeout=max(_get_command_timeout(), 60)) TypeError: '>' not supported between instances of 'int' and 'NoneType'

Root Cause

Root cause: _get_command_timeout() can return None after cleanup_all_browsers() resets the cache (_cached_command_timeout = None, _command_timeout_resolved = False). On the subsequent call, there's a window where _command_timeout_resolved is True but _cached_command_timeout is still None, causing max(None, 60) to throw.

Fix Action

Fix / Workaround

ERROR tools.registry: Tool browser_navigate dispatch error: '>' not supported between instances of 'int' and 'NoneType'                               
  Traceback (most recent call last):
    File "/Users/goofy/hermes-agent/tools/registry.py", line 163, in dispatch                                                                           
      return entry.handler(args, **kwargs)                                                                                                            
    File "/Users/goofy/hermes-agent/tools/browser_tool.py", line 2310, in <lambda>
      handler=lambda args, **kw: browser_navigate(url=args.get("url", ""), task_id=kw.get("task_id")),
    File "/Users/goofy/hermes-agent/tools/browser_tool.py", line 1333, in browser_navigate
      result = _run_browser_command(effective_task_id, "open", [url], timeout=max(_get_command_timeout(), 60))
  TypeError: '>' not supported between instances of 'int' and 'NoneType'

PR fix notes

PR #14338: fix(browser_tool): prevent _get_command_timeout from returning None on exception path

Description (problem / solution / changelog)

Fixes #14331

The bug

_get_command_timeout() flipped _command_timeout_resolved = True before assigning _cached_command_timeout = result. If the body raised between those two statements (e.g. read_raw_config() failing, or a re-entrant import during config resolution), the function exited with resolved=True and cache=None. Every subsequent call hit the fast path and returned None.

cleanup_all_browsers() had the symmetric ordering problem: it nulled the cache before flipping resolved=False, leaving the same broken state for any in-flight reader.

Downstream, max(_get_command_timeout(), 60) then crashed with TypeError: '>' not supported between instances of 'int' and 'NoneType' and killed the agent session.

Not a concurrent race in the threading sense — Python's GIL prevents that here. It's a torn cache state on the exception/re-entry path that, once entered, is sticky.

Changes

  • _get_command_timeout: assign _cached_command_timeout before setting _command_timeout_resolved = True. Tightened the fast path to require both flag and cache to be valid.
  • cleanup_all_browsers: flip _command_timeout_resolved = False before nulling _cached_command_timeout — closes the symmetric reset window.
  • New _safe_command_timeout() helper: defense in depth; falls back to DEFAULT_COMMAND_TIMEOUT if the underlying value is ever None. Uses is not None rather than or so a legitimately configured 0 is preserved.
  • Updated both call sites (browser_tool.py:1116 and the browser_navigate max(..., 60) site) to use the safe helper.
  • New regression tests (tests/tools/test_browser_command_timeout_race.py, 6 cases) exercise the exact failure window: config raising mid-resolution, cleanup ordering invariant, the max(..., 60) call-site pattern, and the is not None vs or distinction for a legitimate 0.

Verification

uv run --frozen --python 3.11 --extra dev pytest -o addopts='' \
  tests/tools/test_browser_hardening.py \
  tests/tools/test_browser_cleanup.py \
  tests/tools/test_browser_ssrf_local.py \
  tests/tools/test_browser_command_timeout_race.py -q
44 passed in 0.24s

Notes

  • Minimal, focused diff — no behavior change for the happy path.
  • No new dependencies.
  • Regression tests directly assert the invariant the bug violated (resolved=Truecache is not None) so this can't silently regress.

Changed files

  • tests/tools/test_browser_command_timeout_race.py (added, +109/-0)
  • tools/browser_tool.py (modified, +23/-6)

PR #14344: fix(browser_tool): guard _get_command_timeout() against None after cleanup - closes #14331

Description (problem / solution / changelog)

Summary

cleanup_all_browsers() resets _cached_command_timeout = None and _command_timeout_resolved = False. On the very next call to _get_command_timeout(), the code sets _command_timeout_resolved = True before assigning _cached_command_timeout, creating a window where the function returns None.

Both call sites then fail:

# line 1116
timeout = _get_command_timeout()          # → None passed into _run_browser_command

# line 1459
timeout=max(_get_command_timeout(), 60)   # → TypeError: > not supported between int and NoneType

Fix

Fall back to DEFAULT_COMMAND_TIMEOUT at both call sites:

# line 1116
timeout = _get_command_timeout() or DEFAULT_COMMAND_TIMEOUT

# line 1459
timeout = max(_get_command_timeout() or DEFAULT_COMMAND_TIMEOUT, 60)

This is the minimal, zero-risk fix: DEFAULT_COMMAND_TIMEOUT is already the intended fallback value inside _get_command_timeout() itself — we just surface it explicitly at the call sites where None can slip through during the cleanup reset window.

Verification

  • python3 -m py_compile tools/browser_tool.py — passes
  • Both fix lines verified against the exact lines identified in #14331

Closes #14331

Changed files

  • tools/browser_tool.py (modified, +2/-2)

PR #14346: fix(browser): guard command timeout cache reset

Description (problem / solution / changelog)

Summary

  • Fixes #14331.
  • Ensures _get_command_timeout() never returns None after browser cleanup/cache reset states.
  • Sets the resolved flag only after the timeout cache has been assigned, and adds defensive fallbacks at browser command call sites.

Root cause

_command_timeout_resolved could be true while _cached_command_timeout was still None, so browser_navigate() could evaluate max(None, 60) and crash.

Tests

  • uv run --frozen --python 3.11 --extra dev pytest -o addopts='' tests/tools/test_browser_hardening.py tests/tools/test_browser_cleanup.py tests/tools/test_browser_ssrf_local.py -q
  • git diff --check

Changed files

  • tests/tools/test_browser_hardening.py (modified, +27/-0)
  • tools/browser_tool.py (modified, +5/-4)

PR #14779: fix(tools): guard _get_command_timeout against None return after browser cleanup race

Description (problem / solution / changelog)

What does this PR do?

Guards _get_command_timeout() in browser_tool.py against returning None after a browser cleanup race condition, preventing a TypeError crash.

Related Issue

Fixes #14783

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • tools/browser_tool.py: Added None guard in _get_command_timeout()
  • tests/tools/test_browser_timeout_race.py: 3 tests for the race condition

How to Test

python -m pytest -o 'addopts=' tests/tools/test_browser_timeout_race.py -v

Result: 3 passed.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits
  • I searched for existing PRs
  • My PR contains only changes related to this fix
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes
  • I've tested on my platform: macOS 15 (Darwin 24.6.0), Python 3.14.2

Documentation & Housekeeping

  • N/A for all documentation items

Changed files

  • tests/tools/test_browser_timeout_race.py (added, +47/-0)
  • tools/browser_tool.py (modified, +1/-1)

PR #14843: fix(browser): guard command timeout cache invalidation

Description (problem / solution / changelog)

Summary

  • make tools.browser_tool._get_command_timeout() fall back to the default timeout when cleanup invalidates the cached value mid-read
  • preserve the existing cache behavior for valid integer timeouts
  • add a regression test for the cleanup race window

Testing

  • python3 -m pytest -o addopts='' -q tests/tools/test_browser_hardening.py

Closes #14783

Changed files

  • tests/tools/test_browser_hardening.py (modified, +8/-0)
  • tools/browser_tool.py (modified, +8/-1)

Code Example

version:          0.10.0 (2026.4.16) [14220291]                                                                                                     
  os:               Darwin 21.6.0 x86_64
  python:           3.11.14
  openai_sdk:       2.30.0
  model:            nous / moonshotai/kimi-k2.6
  terminal:         local

---

ERROR tools.registry: Tool browser_navigate dispatch error: '>' not supported between instances of 'int' and 'NoneType'                               
  Traceback (most recent call last):
    File "/Users/goofy/hermes-agent/tools/registry.py", line 163, in dispatch                                                                           
      return entry.handler(args, **kwargs)                                                                                                            
    File "/Users/goofy/hermes-agent/tools/browser_tool.py", line 2310, in <lambda>
      handler=lambda args, **kw: browser_navigate(url=args.get("url", ""), task_id=kw.get("task_id")),
    File "/Users/goofy/hermes-agent/tools/browser_tool.py", line 1333, in browser_navigate
      result = _run_browser_command(effective_task_id, "open", [url], timeout=max(_get_command_timeout(), 60))
  TypeError: '>' not supported between instances of 'int' and 'NoneType'
RAW_BUFFERClick to expand / collapse

Bug Description

After running hermes update (94 commits, v0.10.0 build 14220291), any agent session that calls browser_navigate crashes immediately with:

TypeError: '>' not supported between instances of 'int' and 'NoneType' File "tools/browser_tool.py", line 1459, in browser_navigate result = _run_browser_command(..., timeout=max(_get_command_timeout(), 60))

Root cause: _get_command_timeout() can return None after cleanup_all_browsers() resets the cache (_cached_command_timeout = None, _command_timeout_resolved = False). On the subsequent call, there's a window where _command_timeout_resolved is True but _cached_command_timeout is still None, causing max(None, 60) to throw.

Affects both call sites — line 1116 and line 1459 in browser_tool.py.

Fix:

line 1116

timeout = _get_command_timeout() or DEFAULT_COMMAND_TIMEOUT

line 1459

timeout=max(_get_command_timeout() or DEFAULT_COMMAND_TIMEOUT, 60)

Environment: Darwin 21.6.0 x86_64, Python 3.11.14, Hermes v0.10.0 [14220291]

Steps to Reproduce

  1. Run hermes update (installs latest build)

  2. Start a gateway session with any profile that has browser tools enabled:
    hermes chat -q "Crawl https://lpepc.org/ and summarize every page you find"

  3. Agent calls browser_navigate repeatedly across multiple pages

  4. After several navigations (cleanup_all_browsers() fires between pages), the next browser_navigate call crashes:

    TypeError: '>' not supported between instances of 'int' and 'NoneType' browser_tool.py line 1459: timeout=max(_get_command_timeout(), 60)

  5. Session dies. Paperclip reports "live execution disappeared".

Key detail: It doesn't crash on the first browser_navigate call — only after cleanup_all_browsers() has been called at least once mid-session, which resets _cached_command_timeout = None and _command_timeout_resolved = False. The next call sets _command_timeout_resolved = True before assigning _cached_command_timeout, leaving a window where it returns None.

Expected Behavior

browser_navigate navigates to the URL and returns the page content without crashing

Actual Behavior

browser_navigate tool throws TypeError and crashes the agent session:

TypeError: '>' not supported between instances of 'int' and 'NoneType'

The session dies mid-task. Paperclip sees the execution disappear and
retries, but retries also crash. Task gets moved to blocked.

Affected Component

Tools (terminal, file ops, web, code execution, etc.)

Messaging Platform (if gateway-related)

No response

Debug Report

version:          0.10.0 (2026.4.16) [14220291]                                                                                                     
  os:               Darwin 21.6.0 x86_64
  python:           3.11.14
  openai_sdk:       2.30.0
  model:            nous / moonshotai/kimi-k2.6
  terminal:         local

Operating System

Darwin 21.6.0 x86_64

Python Version

3.11.14

Hermes Version

0.10.0

Additional Logs / Traceback (optional)

ERROR tools.registry: Tool browser_navigate dispatch error: '>' not supported between instances of 'int' and 'NoneType'                               
  Traceback (most recent call last):
    File "/Users/goofy/hermes-agent/tools/registry.py", line 163, in dispatch                                                                           
      return entry.handler(args, **kwargs)                                                                                                            
    File "/Users/goofy/hermes-agent/tools/browser_tool.py", line 2310, in <lambda>
      handler=lambda args, **kw: browser_navigate(url=args.get("url", ""), task_id=kw.get("task_id")),
    File "/Users/goofy/hermes-agent/tools/browser_tool.py", line 1333, in browser_navigate
      result = _run_browser_command(effective_task_id, "open", [url], timeout=max(_get_command_timeout(), 60))
  TypeError: '>' not supported between instances of 'int' and 'NoneType'

Root Cause Analysis (optional)

_get_command_timeout() returns None after cleanup_all_browsers() resets
the cache (_cached_command_timeout = None, _command_timeout_resolved = False).

On the next call, _command_timeout_resolved is set to True before _cached_command_timeout is assigned, leaving a window where the function
returns None instead of the default (30s).

max(None, 60) then throws TypeError in Python 3.

Proposed Fix (optional)

Fix:

line 1116

timeout = _get_command_timeout() or DEFAULT_COMMAND_TIMEOUT

line 1459

timeout=max(_get_command_timeout() or DEFAULT_COMMAND_TIMEOUT, 60)

Are you willing to submit a PR for this?

  • I'd like to fix this myself and submit a PR

extent analysis

TL;DR

The issue can be fixed by modifying the browser_tool.py file to handle the case where _get_command_timeout() returns None by providing a default timeout value.

Guidance

  • Modify the browser_tool.py file at lines 1116 and 1459 to use the or operator to provide a default timeout value when _get_command_timeout() returns None.
  • Verify that the fix works by running the hermes update command and starting a new gateway session with browser tools enabled.
  • Test the browser_navigate tool to ensure it no longer crashes with a TypeError.
  • Consider submitting a PR with the proposed fix to resolve the issue permanently.

Example

# line 1116
timeout = _get_command_timeout() or DEFAULT_COMMAND_TIMEOUT

# line 1459
timeout = max(_get_command_timeout() or DEFAULT_COMMAND_TIMEOUT, 60)

Notes

The proposed fix assumes that DEFAULT_COMMAND_TIMEOUT is defined and set to a valid timeout value. If this is not the case, additional modifications may be necessary.

Recommendation

Apply the workaround by modifying the browser_tool.py file as described, as this will allow the browser_navigate tool to function correctly until a permanent fix can be implemented.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING