sgl-project/sglang · error · ValueError
browser.search requires a query
Error message
browser.search requires a query
What it means
SGLang's browser tool dispatch rejects a browser.search action whose parsed JSON arguments contain no truthy 'query' field. The search path requires at least a query string before it can call the underlying Exa search client.
Source
Thrown at python/sglang/srt/entrypoints/tool.py:72
try:
args = orjson.loads(last_msg.content[0].text)
result_text = await self._dispatch_browser_call(context, recipient, args)
except Exception as exc:
logger.exception("Browser tool call failed")
result_text = f"Browser tool call failed: {exc}"
content = TextContent(text=result_text)
author = Author(role=Role.TOOL, name=recipient)
return [Message(author=author, content=[content], recipient=Role.ASSISTANT)]
async def _dispatch_browser_call(
self, context: "ConversationContext", recipient: str, args: dict[str, Any]
) -> str:
if recipient == "browser.search":
query = args.get("query")
if not query:
raise ValueError("browser.search requires a query")
data = await self.exa_client.search(query)
return self._format_search_results(context, query, data)
if recipient == "browser.open":
url = self._resolve_url(context, args)
data = await self.exa_client.contents([url])
return self._format_page_contents(context, url, data)
if recipient == "browser.find":
pattern = args.get("pattern")
if not pattern:
raise ValueError("browser.find requires a pattern")
return await self._find_pattern(context, args, pattern)
raise ValueError(f"Unknown browser action: {recipient}")
def _browser_state(self, context: "ConversationContext") -> dict[str, Any]:
state = getattr(context, "_sglang_exa_browser_state", None)View on GitHub (pinned to 0132848349)
Solutions
- Ensure the tool-call JSON includes a non-empty "query" string
- Validate args before dispatch and re-prompt the model to correct empty arguments
- Align the tool schema advertised to the model with {"query": string, required}
Example fix
# before
args = {"q": "sglang"}
# after
args = {"query": "sglang"} Defensive patterns
Strategy: validation
Validate before calling
args = orjson.loads(last_msg.content[0].text)
if not args.get("query"):
raise ValueError("browser.search requires a query") # fail fast client-side Type guard
def valid_search_args(args: dict) -> bool:
return isinstance(args.get("query"), str) and bool(args["query"].strip()) Try / catch
try:
out = await tool._dispatch_browser_call(context, "browser.search", args)
except ValueError as e:
if "requires a query" in str(e):
args["query"] = fallback_query # or re-prompt the model
out = await tool._dispatch_browser_call(context, "browser.search", args) Prevention
- Validate parsed tool JSON against the tool schema before dispatch
- Advertise required parameters clearly in the tool prompt/schema
When it happens
Trigger: Dispatching recipient 'browser.search' with args like {}, {"query": ""}, or {"query": null} after orjson parsing of the message content.
Common situations: A model emitting malformed/empty tool arguments (hallucinated schema), a client constructing browser.search calls manually without a query, or JSON schema drift where the field was renamed (e.g. q instead of query).
Related errors
- browser.find requires a pattern
- browser.open requires a cursor or url
- No browser tool call found
- Unknown browser action: {recipient}
- Unknown browser cursor: {cursor}
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/667439662361f867.
Report an issue: GitHub.