{"record":{"id":"5e3ad2feed6814f1","repo":"sgl-project/sglang","slug":"invalid-number-of-contents-in-browser-message","errorCode":null,"errorMessage":"Invalid number of contents in browser message","messagePattern":"Invalid number of contents in browser message","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/entrypoints/harmony_utils.py","lineNumber":258,"sourceCode":"    return get_encoding().stop_tokens_for_assistant_actions()\n\n\ndef get_streamable_parser_for_assistant() -> StreamableParser:\n    return StreamableParser(get_encoding(), role=Role.ASSISTANT)\n\n\ndef parse_output_message(message: Message):\n    if message.author.role != \"assistant\":\n        # This is a message from a tool to the assistant (e.g., search result).\n        # Don't include it in the final output for now. This aligns with\n        # OpenAI's behavior on models like o4-mini.\n        return []\n\n    output_items = []\n    recipient = message.recipient\n    if recipient is not None and recipient.startswith(\"browser.\"):\n        if len(message.content) != 1:\n            raise ValueError(\"Invalid number of contents in browser message\")\n        content = message.content[0]\n        browser_call = orjson.loads(content.text)\n        # TODO: translate to url properly!\n        if recipient == \"browser.search\":\n            action = ActionSearch(\n                query=f\"cursor:{browser_call.get('query', '')}\", type=\"search\"\n            )\n        elif recipient == \"browser.open\":\n            action = ActionOpenPage(\n                url=f\"cursor:{browser_call.get('url', '')}\", type=\"open_page\"\n            )\n        elif recipient == \"browser.find\":\n            action = ActionFind(\n                pattern=browser_call[\"pattern\"],\n                url=f\"cursor:{browser_call.get('url', '')}\",\n                type=\"find\",\n            )\n        else:","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/entrypoints/harmony_utils.py#L240-L276","documentation":"For harmony messages addressed to a 'browser.*' recipient, parse_output_message expects exactly one content part (the JSON-encoded browser call). If message.content has any length other than 1, the structure is ambiguous and parsing aborts.","triggerScenarios":"A model-produced or hand-crafted message with recipient like 'browser.search' whose content list is empty or has 2+ parts.","commonSituations":"Malformed model output splitting the browser-call JSON across multiple content blocks; clients assembling harmony messages manually and appending extra text parts.","solutions":["Ensure browser.* messages contain exactly one content part holding the full JSON payload","If post-processing model output, merge split content parts into one before parsing","Upgrade sglang if a newer version tolerates/normalizes multi-part browser messages"],"exampleFix":"# before\nmsg = Message(..., recipient=\"browser.search\", content=[p1, p2])\n# after\nmsg = Message(..., recipient=\"browser.search\", content=[merged_single_part])","handlingStrategy":"validation","validationCode":"if message.recipient and message.recipient.startswith(\"browser.\"):\n    assert len(message.content) == 1, \"browser messages need exactly one content part\"","typeGuard":"def is_wellformed_browser_message(message) -> bool:\n    return (\n        message.recipient is not None\n        and message.recipient.startswith(\"browser.\")\n        and len(message.content) == 1\n    )","tryCatchPattern":"try:\n    items = parse_output_message(message)\nexcept ValueError as e:\n    if \"Invalid number of contents\" in str(e):\n        return []  # drop malformed browser message\n    raise","preventionTips":["When building browser messages, always attach a single JSON content part","Validate model output structure before parsing in post-processing pipelines"],"tags":["harmony","browser-tool","message-structure","validation","sglang"],"backgroundTag":"message-schema-validation-failed","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}