{"record":{"id":"9dc824b9d6f3f3fb","repo":"FoundationAgents/MetaGPT","slug":"invalid-scroll-action-step","errorCode":null,"errorMessage":"Invalid scroll action {step}","messagePattern":"Invalid scroll action (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"metagpt/utils/a11y_tree.py","lineNumber":67,"sourceCode":"            match.group(1),\n            match.group(2),\n            match.group(3),\n        )\n        if enter_flag == \"1\":\n            text += \"\\n\"\n        await click_element(page, get_backend_node_id(element_id, accessibility_tree))\n        await type_text(page, text)\n    elif func == \"press\":\n        match = re.search(r\"press ?\\[(.+)\\]\", step)\n        if not match:\n            raise ValueError(f\"Invalid press action {step}\")\n        key = match.group(1)\n        await key_press(page, key)\n    elif func == \"scroll\":\n        # up or down\n        match = re.search(r\"scroll ?\\[?(up|down)\\]?\", step)\n        if not match:\n            raise ValueError(f\"Invalid scroll action {step}\")\n        direction = match.group(1)\n        await scroll_page(page, direction)\n    elif func == \"goto\":\n        match = re.search(r\"goto ?\\[(.+)\\]\", step)\n        if not match:\n            raise ValueError(f\"Invalid goto action {step}\")\n        url = match.group(1)\n        await page.goto(url)\n    elif func == \"new_tab\":\n        page = await browser_ctx.new_page()\n    elif func == \"go_back\":\n        await page.go_back()\n    elif func == \"go_forward\":\n        await page.go_forward()\n    elif func == \"tab_focus\":\n        match = re.search(r\"tab_focus ?\\[(\\d+)\\]\", step)\n        if not match:\n            raise ValueError(f\"Invalid tab_focus action {step}\")","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/utils/a11y_tree.py#L49-L85","documentation":"MetaGPT's browser agent raises this in execute_action when a step classified as a scroll fails to match r'scroll ?\\[?(up|down)\\]?'. The parser only accepts 'scroll [up]', 'scroll [down]', or 'scroll up'/'scroll down' variants, so any other direction word or malformed text triggers the error.","triggerScenarios":"execute_action(page, 'scroll [left]') or 'scroll [top]'); 'scroll upward' (only bare 'up'/'down' match); 'scroll[]' with empty direction; LLM emitting 'scroll to bottom' prose instead of the action syntax.","commonSituations":"LLM outputs horizontal scrolling or 'to top/bottom' phrasing that the strict up|down alternation rejects. Also happens when the step string gets truncated or has extra characters inside the brackets.","solutions":["Normalize the step to 'scroll [up]' or 'scroll [down]' before calling execute_action.","Log the offending step string to confirm what the LLM actually emitted.","Update the action prompt to enumerate only scroll up/down as valid actions.","Add a pre-check regex and retry the LLM call when it fails."],"exampleFix":"# before\nawait execute_action(page, 'scroll [top]')  # raises Invalid scroll action\n\n# after\nawait execute_action(page, 'scroll [up]')","handlingStrategy":"validation","validationCode":"import re\n\ndef is_valid_scroll(step: str) -> bool:\n    return bool(re.search(r\"scroll ?\\[?(up|down)\\]?\", step))","typeGuard":null,"tryCatchPattern":"try:\n    await execute_action(page, step)\nexcept ValueError as e:\n    if 'Invalid scroll action' in str(e):\n        step = 'scroll [down]' if 'down' in step else 'scroll [up]'  # normalize and retry once","preventionTips":["Constrain prompts to only scroll up / scroll down actions.","Normalize LLM scroll phrasing (top->up, bottom->down) before dispatch."],"tags":["metagpt","browser-agent","llm-output","regex","validation"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}