{"record":{"id":"c704375b7f2e5935","repo":"browser-use/browser-use","slug":"success-true-can-only-be-set-when-is-done-true-fo","errorCode":null,"errorMessage":"success=True can only be set when is_done=True. For regular actions that succeed, leave success as None. Use success=False only for actions that fail.","messagePattern":"success=True can only be set when is_done=True\\. For regular actions that succeed, leave success as None\\. Use success=False only for actions that fail\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"browser_use/agent/views.py","lineNumber":344,"sourceCode":"\t# Always include in long term memory\n\tlong_term_memory: str | None = None  # Memory of this action\n\n\t# if update_only_read_state is True we add the extracted_content to the agent context only once for the next step\n\t# if update_only_read_state is False we add the extracted_content to the agent long term memory if no long_term_memory is provided\n\textracted_content: str | None = None\n\tinclude_extracted_content_only_once: bool = False  # Whether the extracted content should be used to update the read_state\n\n\t# Metadata for observability (e.g., click coordinates)\n\tmetadata: dict | None = None\n\n\t# Deprecated\n\tinclude_in_memory: bool = False  # whether to include in extracted_content inside long_term_memory\n\n\t@model_validator(mode='after')\n\tdef validate_success_requires_done(self):\n\t\t\"\"\"Ensure success=True can only be set when is_done=True\"\"\"\n\t\tif self.success is True and self.is_done is not True:\n\t\t\traise ValueError(\n\t\t\t\t'success=True can only be set when is_done=True. '\n\t\t\t\t'For regular actions that succeed, leave success as None. '\n\t\t\t\t'Use success=False only for actions that fail.'\n\t\t\t)\n\t\treturn self\n\n\nclass RerunSummaryAction(BaseModel):\n\t\"\"\"AI-generated summary for rerun completion\"\"\"\n\n\tsummary: str = Field(description='Summary of what happened during the rerun')\n\tsuccess: bool = Field(description='Whether the rerun completed successfully based on visual inspection')\n\tcompletion_status: Literal['complete', 'partial', 'failed'] = Field(\n\t\tdescription='Status of rerun completion: complete (all steps succeeded), partial (some steps succeeded), failed (task did not complete)'\n\t)\n\n\nclass StepMetadata(BaseModel):","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/browser-use/browser-use/blob/6c73fced2f6d45a11d88622fe56365a5fe18f28b/browser_use/agent/views.py#L326-L362","documentation":"`ActionResult` uses a three-valued `success` field: None (default, ordinary successful action), False (action failed), and True — which is reserved exclusively for terminal results where `is_done=True`. A Pydantic model validator rejects `success=True` on any non-done action, because success-flags on intermediate actions would corrupt the agent's evaluation of whether the overall task succeeded.","triggerScenarios":"A custom `@tools.action` returning `ActionResult(success=True)` without `is_done=True` — e.g. returning success=True on each completed sub-step, or copied from a done-style example.","commonSituations":"Writing custom tools that mimic older ActionResult semantics; porting code where success was a plain boolean; marking milestones with success=True instead of extracted_content/long_term_memory.","solutions":["Drop `success=True` from intermediate results — return `ActionResult(extracted_content='...')` or `long_term_memory='...'`.","Only set `success=True` together with `is_done=True` on the final result.","Use `success=False` (with `error=`) exclusively for failed tool calls."],"exampleFix":"# before\n@tools.action('Fetch order status')\nasync def order_status(order_id: str) -> ActionResult:\n    return ActionResult(success=True, extracted_content='shipped')\n\n# after\n@tools.action('Fetch order status')\nasync def order_status(order_id: str) -> ActionResult:\n    return ActionResult(extracted_content='shipped')  # success stays None","handlingStrategy":"validation","validationCode":null,"typeGuard":"def valid_action_result(result) -> bool:\n    return not (result.get('success') is True and result.get('is_done') is not True)","tryCatchPattern":null,"preventionTips":["In custom tools, never set success on non-done results — use extracted_content/long_term_memory.","Add a unit test asserting your tool factories never emit success=True without is_done=True."],"tags":["api-misuse","custom-tools","validation","actionresult"],"backgroundTag":null,"analyzedSha":"6c73fced2f6d45a11d88622fe56365a5fe18f28b","analyzedAt":"2026-08-14T19:42:40.557Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}