Bug: evaluate hides JavaScript exception details behind "Uncaught"

Author: blgbr0Created Sep 9, 2026Updated Sep 13, 2026
Labelsbug

Browser Use Version

0.13.10; upstream commit 2b1f9d377999a59fe7627c1a5aa88c12aa42e11f

Bug Description, Steps to Reproduce, Screenshots

The evaluate action discards the useful part of Chromium's JavaScript exception and returns only JavaScript execution error: Uncaught. This is reproducible with a direct tool call on about:blank; no LLM, credentials, iframe, or external website is needed.

For example, return 42; is invalid at the top level. Chromium reports SyntaxError: Illegal return statement, but the action reads only exceptionDetails.text and drops exceptionDetails.exception.description and the location.

Steps and observed behavior

  1. Run the Python reproducer below against the specified upstream commit.
  2. Compare ActionResult.error with the raw CDP exception from the same expression.
  3. The action reports only Uncaught, while CDP identifies the syntax error.

Expected behavior and impact

Return the browser's exception type/message and available line/column through the existing ActionResult.error path. The same information loss affects runtime errors and rejected promises. Losing this diagnostic makes agent recovery and human debugging harder: the caller cannot distinguish malformed JavaScript from a missing variable or a page access error.

The failing script should still fail normally. This report concerns error feedback; it does not request automatic wrapping or re-execution of JavaScript.

Related: #3620 previously showed the generic Uncaught symptom in a quote-rewriting issue. #5277 addresses source rewriting, while this report concerns the exception details lost after CDP returns. I have a focused fix with real Chromium regression coverage.

Failing Python Code

import asyncio

from browser_use.browser import BrowserProfile, BrowserSession
from browser_use.tools.service import Tools


async def main():
    browser = BrowserSession(
        browser_profile=BrowserProfile(
            headless=True,
            user_data_dir=None,
            use_cloud=False,
            enable_default_extensions=False,
        )
    )
    await browser.start()
    try:
        await browser.navigate_to('about:blank')
        result = await Tools().registry.execute_action(
            'evaluate', {'code': 'return 42;'}, browser_session=browser
        )
        print('ACTION_RESULT:', result.error)

        cdp = await browser.get_or_create_cdp_session()
        raw = await cdp.cdp_client.send.Runtime.evaluate(
            params={
                'expression': 'return 42;',
                'returnByValue': True,
                'awaitPromise': True,
            },
            session_id=cdp.session_id,
        )
        print('CDP_EXCEPTION:', raw['exceptionDetails']['exception']['description'])
    finally:
        await browser.kill()
        await browser.event_bus.stop(clear=True, timeout=5)


asyncio.run(main())

LLM Model

None. Reproduced through Tools.registry.execute_action without an Agent or LLM.

Operating System & Browser Versions

Windows x64, CPython 3.12.13, local headless Chrome/152.0.7977.83 (CDP protocol 1.3).

Full DEBUG Log Output

Relevant output from the minimal reproducer:

ACTION_RESULT: JavaScript Execution Failed:
JavaScript execution error: Uncaught

Validated Code (after quote fixing):
return 42;

CDP_EXCEPTION: SyntaxError: Illegal return statement