OpenBMB/ChatDev · error · ValidationError

Task prompt cannot be empty

Error message

Task prompt cannot be empty

What it means

The sync runner requires either a non-blank task_prompt or at least one attachment; when both are absent it raises ValidationError('Task prompt cannot be empty'). A whitespace-only prompt counts as empty.

Source

Thrown at server/routes/execute_sync.py:87

def _run_workflow_with_logger(
    *,
    yaml_file: Union[str, Path],
    task_prompt: str,
    attachments: Optional[Sequence[Union[str, Path]]],
    session_name: Optional[str],
    variables: Optional[dict],
    log_level: Optional[LogLevel],
    log_callback,
) -> tuple[Optional[Message], dict[str, Any]]:
    ensure_schema_registry_populated()

    yaml_path = _resolve_yaml_path(yaml_file)
    if not yaml_path.exists():
        raise FileNotFoundError(f"YAML file not found: {yaml_path}")

    attachments = attachments or []
    if (not task_prompt or not task_prompt.strip()) and not attachments:
        raise ValidationError(
            "Task prompt cannot be empty",
            details={"task_prompt_provided": bool(task_prompt)},
        )

    design = load_config(yaml_path, vars_override=variables)
    normalized_session = _normalize_session_name(yaml_path, session_name)

    graph_config = GraphConfig.from_definition(
        design.graph,
        name=normalized_session,
        output_root=OUTPUT_ROOT,
        source_path=str(yaml_path),
        vars=design.vars,
    )

    if log_level:
        graph_config.log_level = log_level
        graph_config.definition.log_level = log_level

View on GitHub (pinned to 4fb2db0ea9)

Solutions

  1. Provide a non-empty task_prompt (trim check is applied)
  2. Or include at least one attachment if the workflow is promptless
  3. Validate and reject empty prompts client-side before submission

Example fix

# before
{"yaml_file": "wf.yaml", "task_prompt": "  "}
# after
{"yaml_file": "wf.yaml", "task_prompt": "Summarize the attached report"}
Defensive patterns

Strategy: validation

Validate before calling

prompt = (task_prompt or '').strip()
if not prompt and not attachments:
    raise ValueError('provide task_prompt or at least one attachment')

Type guard

def has_runnable_input(prompt: str | None, attachments: list) -> bool:
    return bool((prompt or '').strip()) or bool(attachments)

Try / catch

try:
    client.run_workflow_sync(...)
except HTTPError as e:
    if e.response.status_code == 400 and 'Task prompt cannot be empty' in e.response.text:
        req['task_prompt'] = default_prompt; retry(req)

Prevention

When it happens

Trigger: POST /workflow/run with task_prompt="", task_prompt=" ", or null, and an empty/omitted attachments list.

Common situations: Clients where the prompt field is optional and left blank; forms where whitespace was submitted; automated pipelines that pass only variables but no task.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


AI-assisted analysis of OpenBMB/ChatDev@4fb2db0ea9 (2026-08-27). Data as JSON: /api/errors/e780fd88cf0f6096. Report an issue: GitHub.