browser-use/browser-use · error · ValueError
JavaScript code must start with (...args) => format. Got: {p
Error message
JavaScript code must start with (...args) => format. Got: {page_function[:50]}... What it means
Raised by ActorPage.evaluate() when the page_function does not begin with '(' or does not contain '=>'. The library only accepts JavaScript written as an arrow function, e.g. '() => document.title', because it wraps the code as '({page_function})()' before sending it to CDP Runtime.evaluate. Any other syntax (bare statements, 'function' declarations, async IIFE) is rejected before execution.
Source
Thrown at browser_use/actor/page.py:121
async def evaluate(self, page_function: str, *args) -> str:
"""Execute JavaScript in the target.
Args:
page_function: JavaScript code that MUST start with (...args) => format
*args: Arguments to pass to the function
Returns:
String representation of the JavaScript execution result.
Objects and arrays are JSON-stringified.
"""
session_id = await self._ensure_session()
# Clean and fix common JavaScript string parsing issues
page_function = self._fix_javascript_string(page_function)
# Enforce arrow function format
if not (page_function.startswith('(') and '=>' in page_function):
raise ValueError(f'JavaScript code must start with (...args) => format. Got: {page_function[:50]}...')
# Build the expression - call the arrow function with provided args
if args:
# Convert args to JSON representation for safe passing
import json
arg_strs = [json.dumps(arg) for arg in args]
expression = f'({page_function})({", ".join(arg_strs)})'
else:
expression = f'({page_function})()'
# Debug: log the actual expression being evaluated
logger.debug(f'Evaluating JavaScript: {repr(expression)}')
params: 'EvaluateParameters' = {'expression': expression, 'returnByValue': True, 'awaitPromise': True}
result = await self._client.send.Runtime.evaluate(
params,
session_id=session_id,View on GitHub (pinned to 6c73fced2f)
Solutions
- Rewrite the code as an arrow function: page.evaluate('() => document.title')
- Wrap statements in a zero-arg arrow body: page.evaluate('() => { window.scrollTo(0, 500); return "done"; }')
- If the string came from an LLM tool call, pre-validate it client-side with a regex like r'^\\s*\\(.*=>'
- Upgrade/check version: newer browser-use releases may auto-wrap non-arrow code in some code paths, but do not rely on it
Example fix
# before
await page.evaluate('document.title')
# after
await page.evaluate('() => document.title') Defensive patterns
Strategy: validation
Validate before calling
import re
ARROW_RE = re.compile(r'^\s*\(.*=>', re.DOTALL)
def as_arrow_fn(js: str) -> str:
js = js.strip()
if not ARROW_RE.match(js):
return f'() => {{ {js} }}' if not js.endswith(';') else f'() => {{ {js} }}'
return js
page_function = as_arrow_fn(page_function)
assert page_function.startswith('(') and '=>' in page_function Type guard
def is_arrow_function(code: str) -> bool:
code = code.strip()
return code.startswith('(') and '=>' in code Try / catch
try:
await page.evaluate(js)
except ValueError as e:
if 'must start with' in str(e):
await page.evaluate(f'() => {{ {js} }}') # one-shot repair
else:
raise Prevention
- Always author evaluate code as '() => ...' from the start
- When an LLM generates evaluate actions, validate the arrow format before executing
- Prefer a shared helper that normalizes JS to arrow format once
When it happens
Trigger: Calling page.evaluate('document.title') or page.evaluate('return 1') (no arrow syntax); passing a statement string like 'window.scrollTo(0, 500)'; passing code that starts with whitespace/quote wrappers that _fix_javascript_string strips so the leading '(' is lost.
Common situations: Developers coming from Playwright's page.evaluate which accepts expressions and function bodies; LLM-generated evaluate actions that emit plain JS statements instead of arrow functions; double-quoted strings that get unwrapped and mangled by the cleaning step.
Related errors
- JavaScript evaluation failed: {result["exceptionDetails"]}
- JavaScript code is empty after cleaning
- Got BrowserSession(is_local=False) but no cdp_url was provid
- Cannot setup CDP connection without CDP URL
- SessionManager not initialized
AI-assisted analysis of browser-use/browser-use@6c73fced2f (2026-08-14).
Data as JSON: /api/errors/0572250b84679985.
Report an issue: GitHub.