{"record":{"id":"1a8bb470a2fc8d0a","repo":"sgl-project/sglang","slug":"browser-find-requires-a-pattern","errorCode":null,"errorMessage":"browser.find requires a pattern","messagePattern":"browser\\.find requires a pattern","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/entrypoints/tool.py","lineNumber":84,"sourceCode":"    async def _dispatch_browser_call(\n        self, context: \"ConversationContext\", recipient: str, args: dict[str, Any]\n    ) -> str:\n        if recipient == \"browser.search\":\n            query = args.get(\"query\")\n            if not query:\n                raise ValueError(\"browser.search requires a query\")\n            data = await self.exa_client.search(query)\n            return self._format_search_results(context, query, data)\n\n        if recipient == \"browser.open\":\n            url = self._resolve_url(context, args)\n            data = await self.exa_client.contents([url])\n            return self._format_page_contents(context, url, data)\n\n        if recipient == \"browser.find\":\n            pattern = args.get(\"pattern\")\n            if not pattern:\n                raise ValueError(\"browser.find requires a pattern\")\n            return await self._find_pattern(context, args, pattern)\n\n        raise ValueError(f\"Unknown browser action: {recipient}\")\n\n    def _browser_state(self, context: \"ConversationContext\") -> dict[str, Any]:\n        state = getattr(context, \"_sglang_exa_browser_state\", None)\n        if state is None:\n            state = {\"pages\": {}, \"page_text\": {}}\n            setattr(context, \"_sglang_exa_browser_state\", state)\n        return state\n\n    def _format_search_results(\n        self, context: \"ConversationContext\", query: str, data: dict[str, Any]\n    ) -> str:\n        state = self._browser_state(context)\n        state[\"pages\"] = {}\n        state[\"page_text\"] = {}\n","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/entrypoints/tool.py#L66-L102","documentation":"SGLang's browser tool dispatch rejects a browser.find action whose arguments lack a truthy 'pattern' field. browser.find searches previously loaded page text for a regex/substring and cannot proceed without a pattern.","triggerScenarios":"Dispatching recipient 'browser.find' with args missing 'pattern', or with an empty/null pattern, e.g. {\"cursor\": \"0\"} only.","commonSituations":"Model emitting browser.find with only a cursor argument and forgetting the pattern, or schema mismatch after changing the tool definition.","solutions":["Include a non-empty \"pattern\" string in browser.find arguments","Validate args['pattern'] before dispatch and re-ask the model if missing","Update the tool schema to mark pattern as required"],"exampleFix":"# before\nargs = {\"cursor\": \"0\"}\n# after\nargs = {\"cursor\": \"0\", \"pattern\": \"pricing\"}","handlingStrategy":"validation","validationCode":"if not args.get(\"pattern\"):\n    raise ValueError(\"browser.find requires a pattern\")","typeGuard":"def valid_find_args(args: dict) -> bool:\n    return isinstance(args.get(\"pattern\"), str) and bool(args[\"pattern\"].strip())","tryCatchPattern":"try:\n    out = await tool._dispatch_browser_call(context, \"browser.find\", args)\nexcept ValueError as e:\n    if \"requires a pattern\" in str(e):\n        # surface to the model for correction\n        ...","preventionTips":["Mark 'pattern' as required in the tool schema exposed to the model","Validate args dict keys before dispatch"],"tags":["browser","find","argument-validation","tool-calling"],"backgroundTag":"missing-required-tool-argument","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}