shareAI-lab/learn-claude-code · error · WorkflowInputError
meta.phases must be a list of non-empty strings
Error message
meta.phases must be a list of non-empty strings
What it means
When meta includes 'phases', it must be a list whose every element is a non-empty string. Anything else — a string, a dict, None, or a list containing empties/non-strings — raises WorkflowInputError. Phases are optional; the check only runs when the key is present.
Source
Thrown at s16_workflow_runtime/code.py:136
# -- Metadata Validation --
def validate_meta(meta):
"""Validate name, description, and optional phases before launch."""
if not isinstance(meta, dict):
raise WorkflowInputError("meta must be an object literal")
if not meta.get("name") or not meta.get("description"):
raise WorkflowInputError("meta requires `name` and `description`")
if not isinstance(meta["name"], str) or not WORKFLOW_NAME_RE.fullmatch(meta["name"]):
raise WorkflowInputError(
"meta.name must be a 1-64 character slug using letters, numbers, '.', '_', or '-'"
)
if not isinstance(meta["description"], str):
raise WorkflowInputError("meta.description must be a string")
if "phases" in meta:
if not isinstance(meta["phases"], list) or not all(
isinstance(phase, str) and phase for phase in meta["phases"]
):
raise WorkflowInputError("meta.phases must be a list of non-empty strings")
return meta
def check_permission(meta, settings=None):
"""Apply the s03 allow/deny gate before launching a workflow."""
settings = settings or {}
if meta["name"] in settings.get("deny", []):
raise WorkflowInputError(f"workflow '{meta['name']}' denied by settings")
return "allow"
# -- Minimal JSON Schema --
class SimpleJsonSchema:
"""Tiny validator backing agent({schema}):
object/array/string/boolean/number + required keys."""
def __init__(self, schema):
self.schema = schemaView on GitHub (pinned to 985456f4ad)
Solutions
- Always use a list of non-empty strings: ["extract", "transform", "load"]
- In YAML, write single phases as 'phases: [extract]' so they parse as lists
- Filter out falsy entries when generating phases programmatically: [p for p in raw if isinstance(p, str) and p]
Example fix
# before
meta = {"name": "etl", "description": "...", "phases": "extract,transform"}
# after
meta = {"name": "etl", "description": "...", "phases": ["extract", "transform"]} Defensive patterns
Strategy: validation
Validate before calling
def phases_are_valid(meta: dict) -> bool:
phases = meta.get("phases")
return phases is None or (
isinstance(phases, list)
and all(isinstance(p, str) and p for p in phases)
)
assert phases_are_valid(meta) Type guard
def meta_phases_ok(meta) -> bool:
if "phases" not in meta:
return True
phases = meta["phases"]
return isinstance(phases, list) and all(isinstance(p, str) and p for p in phases) Try / catch
try:
validate_meta(meta)
except WorkflowInputError as exc:
if "meta.phases" in str(exc):
raw = meta.get("phases")
phases = [p.strip() for p in raw.split(",")] if isinstance(raw, str) else [p for p in raw if isinstance(p, str) and p]
meta = {**meta, "phases": phases}
validate_meta(meta)
else:
raise Prevention
- Write single phases as ["name"] in YAML, not a scalar
- Filter empties when generating phase lists
- Omit the phases key entirely when unused
When it happens
Trigger: meta = {"phases": "extract, transform"} (a single string instead of a list). meta = {"phases": ["extract", ""]} (trailing comma produced an empty element). meta = {"phases": [{"name": "extract"}]} (objects instead of strings).
Common situations: Config formats where a one-element list is written as a scalar (YAML 'phases: extract'). Programmatic phase lists with filtered/empty results. Refactors from structured phase objects to plain names that stop halfway.
Related errors
- meta must be an object literal
- meta.description must be a string
- meta requires `name` and `description`
- meta.name must be a 1-64 character slug using letters, numbe
- invalid workflow runId
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/055410a517180a7f.
Report an issue: GitHub.