FoundationAgents/OpenManus · warning · ToolError
No plan found with ID: {plan_id}
Error message
No plan found with ID: {plan_id} What it means
Raised by _update_plan (app/tool/planning.py:168) when command='update' targets a plan_id not present in the in-memory self.plans dict. The store is process-local (class-level dict), so IDs created in a previous process run or a different worker do not exist here. Checked before any mutation.
Source
Thrown at app/tool/planning.py:168
"step_notes": [""] * len(steps),
}
self.plans[plan_id] = plan
self._current_plan_id = plan_id # Set as active plan
return ToolResult(
output=f"Plan created successfully with ID: {plan_id}\n\n{self._format_plan(plan)}"
)
def _update_plan(
self, plan_id: Optional[str], title: Optional[str], steps: Optional[List[str]]
) -> ToolResult:
"""Update an existing plan with new title or steps."""
if not plan_id:
raise ToolError("Parameter `plan_id` is required for command: update")
if plan_id not in self.plans:
raise ToolError(f"No plan found with ID: {plan_id}")
plan = self.plans[plan_id]
if title:
plan["title"] = title
if steps:
if not isinstance(steps, list) or not all(
isinstance(step, str) for step in steps
):
raise ToolError(
"Parameter `steps` must be a list of strings for command: update"
)
# Preserve existing step statuses for unchanged steps
old_steps = plan["steps"]
old_statuses = plan["step_statuses"]
old_notes = plan["step_notes"]View on GitHub (pinned to 52a13f2a57)
Solutions
- Run command='list' first and use an exact existing plan_id.
- If the plan is genuinely gone (restart/delete), recreate it with command='create' (rebuilding step statuses to not_started).
- If persistence matters, serialize plans outside the tool and replay creates on startup — the tool has no built-in storage.
- Normalize IDs at the caller (strip/consistent casing) to avoid mismatch collisions.
Example fix
// before await planning.execute(command='update', plan_id='release-2', title='T') # typo, never created // after plans = await planning.execute(command='list') # pick exact id from output, then: await planning.execute(command='update', plan_id='release-1', title='T')
Defensive patterns
Strategy: validation
Validate before calling
ids = await list_plan_ids(planning) # via command='list'
if plan_id not in ids:
raise KeyError(f'plan {plan_id!r} not found; existing: {sorted(ids)}')
await planning.execute(command='update', plan_id=plan_id, title=title) Try / catch
try:
await planning.execute(command='update', plan_id=pid, title=t)
except ToolError as e:
if 'No plan found' in str(e):
await planning.execute(command='create', plan_id=pid, title=t, steps=fallback_steps)
else:
raise Prevention
- Keep the set of live plan IDs in caller state and validate before update.
- Recreate plans on process restart if your flow depends on them — the store is in-memory.
- Normalize IDs (strip, consistent casing) wherever they are produced or consumed.
When it happens
Trigger: Calling update with a typo'd or stale plan_id; updating after the plan was deleted (command='delete'); updating in a new process/session that never created the plan (no persistence between restarts).
Common situations: Agent sessions resumed after a process restart expecting plans to persist; horizontal scaling where each worker has its own class-level dict; ID casing/whitespace mismatches ('Plan1' vs 'plan1').
Related errors
- No primary agent available
- File not found: {path}
- Source file not found: {src_path}
- Unrecognized command: {command}. Allowed commands are: creat
- Parameter `plan_id` is required for command: create
AI-assisted analysis of FoundationAgents/OpenManus@52a13f2a57 (2026-08-15).
Data as JSON: /api/errors/4cc8b0f1e8840bc4.
Report an issue: GitHub.