FoundationAgents/OpenManus · warning · ToolError
Parameter `steps` must be a non-empty list of strings for co
Error message
Parameter `steps` must be a non-empty list of strings for command: create
What it means
Raised by _create_plan (app/tool/planning.py:140) when the steps argument for command='create' is None, an empty list, or not a list of strings (any non-str element fails the all() check). Steps drive step_statuses/step_notes arrays ('not_started' * len(steps)), so at least one string step is mandatory at creation.
Source
Thrown at app/tool/planning.py:140
) -> ToolResult:
"""Create a new plan with the given ID, title, and steps."""
if not plan_id:
raise ToolError("Parameter `plan_id` is required for command: create")
if plan_id in self.plans:
raise ToolError(
f"A plan with ID '{plan_id}' already exists. Use 'update' to modify existing plans."
)
if not title:
raise ToolError("Parameter `title` is required for command: create")
if (
not steps
or not isinstance(steps, list)
or not all(isinstance(step, str) for step in steps)
):
raise ToolError(
"Parameter `steps` must be a non-empty list of strings for command: create"
)
# Create a new plan with initialized step statuses
plan = {
"plan_id": plan_id,
"title": title,
"steps": steps,
"step_statuses": ["not_started"] * len(steps),
"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)}"
)View on GitHub (pinned to 52a13f2a57)
Solutions
- Pass a non-empty list of strings: steps=['Install deps', 'Run tests', 'Deploy'].
- If the model returned a single string, wrap/split it: steps=[s.strip() for s in raw.split('\n') if s.strip()].
- If you genuinely need an empty plan, create it with one placeholder step ('Define steps') and later update with the real list.
Example fix
// before await planning.execute(command='create', plan_id='p1', title='T', steps='do things') // after await planning.execute(command='create', plan_id='p1', title='T', steps=['do things'])
Defensive patterns
Strategy: validation
Validate before calling
if not isinstance(steps, list) or not steps or not all(isinstance(s, str) and s.strip() for s in steps):
raise ValueError('steps must be a non-empty list[str]')
await planning.execute(command='create', plan_id=pid, title=title, steps=steps) Type guard
from typing import TypeGuard
def is_step_list(v: object) -> TypeGuard[list[str]]:
return isinstance(v, list) and len(v) > 0 and all(isinstance(s, str) for s in v) Try / catch
try:
await planning.execute(command='create', plan_id=pid, title=t, steps=s)
except ToolError as e:
if 'steps` must be a non-empty list' in str(e):
s = [str(x).strip() for x in s if str(x).strip()] or ['Placeholder step']
await planning.execute(command='create', plan_id=pid, title=t, steps=s)
else:
raise Prevention
- Coerce model output: wrap single strings or split newline-delimited text into list[str].
- Validate with a TypeGuard before the call to keep the error out of the agent loop.
- Never pass tuples/dicts — the tool requires a real list of str.
When it happens
Trigger: Calling create with steps omitted, steps=[], steps='step one' (a plain string, not a list), or steps=['a', 2] (mixed types). JSON configs that pass a dict or nested arrays also fail the isinstance checks.
Common situations: LLM tool calls that summarize steps as one string instead of a list; empty plans attempted as placeholders; steps parsed from YAML/JSON landing as tuples or dicts before reaching the tool.
Related errors
- Parameter `steps` must be a list of strings for command: upd
- No primary agent available
- Unrecognized command: {command}. Allowed commands are: creat
- Parameter `plan_id` is required for command: create
- A plan with ID '{plan_id}' already exists. Use 'update' to m
AI-assisted analysis of FoundationAgents/OpenManus@52a13f2a57 (2026-08-15).
Data as JSON: /api/errors/74b5fb2e58515d5c.
Report an issue: GitHub.