sgl-project/sglang · error · ValueError

browser.open requires a cursor or url

Error message

browser.open requires a cursor or url

What it means

SGLang's browser URL resolver cannot determine what to open: browser.open arguments contain neither a 'url' nor a usable 'cursor' referring to a previously seen search result. One of the two is mandatory.

Source

Thrown at python/sglang/srt/entrypoints/tool.py:196

                or self._best_snippet(page)
                or page.get("summary")
                or ""
            )
            return self._format_matches(pattern, text)

        searchable_text = "\n\n".join(
            self._best_snippet(page) for page in state["pages"].values()
        )
        return self._format_matches(pattern, searchable_text)

    def _resolve_url(self, context: "ConversationContext", args: dict[str, Any]) -> str:
        if args.get("url"):
            return str(args["url"])

        state = self._browser_state(context)
        cursor = self._normalize_cursor(args.get("cursor"))
        if not cursor:
            raise ValueError("browser.open requires a cursor or url")

        page = state["pages"].get(cursor)
        if page is None:
            raise ValueError(f"Unknown browser cursor: {cursor}")

        url = page.get("url") or page.get("id")
        if not url:
            raise ValueError(f"No URL recorded for browser cursor: {cursor}")
        return str(url)

    def _normalize_cursor(self, cursor: Any) -> str | None:
        if cursor is None:
            return None
        cursor_str = str(cursor)
        # GPT-OSS emits 0 as a 1-based cursor; map it to the first result.
        if cursor_str == "0":
            return "1"
        return cursor_str

View on GitHub (pinned to 0132848349)

Solutions

  1. Pass an explicit "url" in browser.open arguments
  2. Or first run browser.search, then reference a result via its "cursor" value
  3. Validate that args contains url or a non-empty cursor before dispatching

Example fix

# before
args = {}
# after
args = {"url": "https://sglang.ai"}
Defensive patterns

Strategy: validation

Validate before calling

if not args.get("url") and not args.get("cursor"):
    raise ValueError("browser.open requires a cursor or url")

Type guard

def resolvable_open_args(args: dict) -> bool:
    return bool(args.get("url") or args.get("cursor"))

Prevention

When it happens

Trigger: Calling browser.open with args like {} or {"cursor": null/""}, after _normalize_cursor returns None and no url key exists.

Common situations: Model emitting browser.open with no arguments, or passing a cursor field under a different name; also first browser.open in a session with no prior browser.search to establish cursors.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/e81191ce3e9f8a1f. Report an issue: GitHub.