{"record":{"id":"19c485383ef68bc4","repo":"FoundationAgents/OpenManus","slug":"parameter-plan-id-is-required-for-command-updat","errorCode":null,"errorMessage":"Parameter `plan_id` is required for command: update","messagePattern":"Parameter `plan_id` is required for command: update","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"warning","filePath":"app/tool/planning.py","lineNumber":165,"sourceCode":"            \"title\": title,\n            \"steps\": steps,\n            \"step_statuses\": [\"not_started\"] * len(steps),\n            \"step_notes\": [\"\"] * len(steps),\n        }\n\n        self.plans[plan_id] = plan\n        self._current_plan_id = plan_id  # Set as active plan\n\n        return ToolResult(\n            output=f\"Plan created successfully with ID: {plan_id}\\n\\n{self._format_plan(plan)}\"\n        )\n\n    def _update_plan(\n        self, plan_id: Optional[str], title: Optional[str], steps: Optional[List[str]]\n    ) -> ToolResult:\n        \"\"\"Update an existing plan with new title or steps.\"\"\"\n        if not plan_id:\n            raise ToolError(\"Parameter `plan_id` is required for command: update\")\n\n        if plan_id not in self.plans:\n            raise ToolError(f\"No plan found with ID: {plan_id}\")\n\n        plan = self.plans[plan_id]\n\n        if title:\n            plan[\"title\"] = title\n\n        if steps:\n            if not isinstance(steps, list) or not all(\n                isinstance(step, str) for step in steps\n            ):\n                raise ToolError(\n                    \"Parameter `steps` must be a list of strings for command: update\"\n                )\n\n            # Preserve existing step statuses for unchanged steps","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/FoundationAgents/OpenManus/blob/52a13f2a57d8c7f6737eefb02ccf569594d44273/app/tool/planning.py#L147-L183","documentation":"Raised by _update_plan (app/tool/planning.py:165) when command='update' is dispatched without a truthy plan_id. Unlike get/mark_step, update has no fallback to the currently active plan — the target plan must be identified explicitly. Validation happens before any mutation, so no partial writes occur.","triggerScenarios":"Calling `planning.execute(command='update', title='New title')` with plan_id omitted or ''. This is easy to hit because the sibling commands get and mark_step do default to the active plan, suggesting (incorrectly) that update would too.","commonSituations":"Models switching between planning commands and assuming uniform optional plan_id semantics; refactors that copy a get call and change only the command string.","solutions":["Pass the plan_id explicitly: `planning.execute(command='update', plan_id='p1', title='New title')`.","In wrappers, resolve the active plan yourself first (planning._current_plan_id or a prior list/get call) and inject it for update calls.","Keep the asymmetry documented in your agent prompt: update requires plan_id; get/mark_step fall back to the active plan."],"exampleFix":"// before\nawait planning.execute(command='update', title='Revised')\n\n// after\nawait planning.execute(command='update', plan_id='p1', title='Revised')","handlingStrategy":"validation","validationCode":"plan_id = plan_id or current_active_id()  # resolve in caller; update has no fallback\nif not plan_id:\n    raise ValueError('update requires an explicit plan_id')\nawait planning.execute(command='update', plan_id=plan_id, title=title)","typeGuard":"def is_plan_id(v: str | None) -> bool:\n    return isinstance(v, str) and bool(v.strip())","tryCatchPattern":"try:\n    await planning.execute(command='update', title=t)\nexcept ToolError as e:\n    if 'plan_id` is required for command: update' in str(e):\n        await planning.execute(command='update', plan_id=await resolve_active_id(), title=t)\n    else:\n        raise","preventionTips":["Remember the asymmetry: update needs plan_id; get/mark_step fall back to the active plan.","Inject plan_id at your wrapper layer for every update call."],"tags":["planning","validation","required-field"],"backgroundTag":null,"analyzedSha":"52a13f2a57d8c7f6737eefb02ccf569594d44273","analyzedAt":"2026-08-15T02:33:49.993Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}