can1357/oh-my-pi · error · ValueError

{context} must be a non-empty string

Error message

{context} must be a non-empty string

What it means

`_require_nonempty_str(value, context)` validates that a value from a prompt TOML data file is a string with non-whitespace content and returns it; otherwise it raises ValueError naming the exact location. It guards `host_tools.toml[<tool>].description`, `host_tools.toml[<tool>].parameters[<name>]`, and phase `name`/`tasks` strings in `todo_phases.toml`.

Source

Thrown at python/robomp/src/persona.py:68


@cache
def _load_toml(name: str) -> Mapping[str, Any]:
    data = tomllib.loads(_load(name))
    if not isinstance(data, Mapping):
        raise ValueError(f"prompt data file {name!r} must contain a TOML table")
    return data


def _require_mapping(value: Any, context: str) -> Mapping[str, Any]:
    if not isinstance(value, Mapping):
        raise ValueError(f"{context} must be a table")
    return value


def _require_nonempty_str(value: Any, context: str) -> str:
    if not isinstance(value, str) or not value.strip():
        raise ValueError(f"{context} must be a non-empty string")
    return value


def seed_phases(task_kind: str) -> list[dict[str, Any]]:
    raw_phases = _load_toml("todo_phases.toml").get(task_kind, [])
    if not isinstance(raw_phases, list):
        raise ValueError(f"todo_phases.toml[{task_kind!r}] must be a list of phases")

    phases: list[dict[str, Any]] = []
    for phase_index, raw_phase in enumerate(raw_phases):
        phase = _require_mapping(raw_phase, f"todo_phases.toml[{task_kind!r}][{phase_index}]")
        name = _require_nonempty_str(
            phase.get("name"),
            f"todo_phases.toml[{task_kind!r}][{phase_index}].name",
        )
        raw_tasks = phase.get("tasks")
        if not isinstance(raw_tasks, list) or not raw_tasks:
            raise ValueError(f"todo_phases.toml[{task_kind!r}][{phase_index}].tasks must be a non-empty list")

View on GitHub (pinned to 9690622007)

Solutions

  1. Read the context in the message to locate the exact `[<tool>]`, `parameters[<name>]`, or `todo_phases[<kind>][i].name/tasks[j]` that is empty/absent
  2. Fill in a meaningful non-empty string at that location, or restore the file with `git checkout -- python/robomp/src/prompts/<file>.toml`
  3. Keep parameter names in `host_tools.toml` in sync with the Python tool definitions after renames
  4. Quickly audit: `python -c "import tomllib; d=tomllib.load(open('host_tools.toml','rb')); [print(k, bool(d[k].get('description','').strip())) for k in d]"`

Example fix

# before (host_tools.toml)
[triage_issue]
description = ""

# after
[triage_issue]
description = "Apply triage labels to the issue"
Defensive patterns

Strategy: validation

Validate before calling

import tomllib
tools = tomllib.load(open("host_tools.toml", "rb"))
for name, entry in tools.items():
    d = entry.get("description")
    assert isinstance(d, str) and d.strip(), f"{name}.description missing/empty"
    for p, pd in entry.get("parameters", {}).items():
        assert isinstance(pd, str) and pd.strip(), f"{name}.parameters[{p}] missing/empty"

Type guard

def is_nonempty_str(value) -> bool:
    return isinstance(value, str) and bool(value.strip())

Try / catch

try:
    desc = host_tool_description(tool_name)
except ValueError as e:
    logger.error("host_tools.toml field missing: %s", e)
    raise  # misconfiguration must be surfaced, not silently defaulted

Prevention

When it happens

Trigger: Calling `host_tool_description(tool)` when `host_tools.toml` lacks a `description` for that tool or sets it to a non-string/empty; `host_tool_parameter_description(tool, param)` when `[tool.parameters]` lacks the parameter key or its value is empty/whitespace; `seed_phases(kind)` when a phase's `name` or an entry of its `tasks` list is missing (None), empty (""), whitespace (" "), or a non-string like an integer.

Common situations: Adding a new host tool to `host_tools.toml` and forgetting the `description` field or a parameter description; renaming a parameter in Python without updating the TOML so the key lookup returns None; an editor stripping content leaving `name = ""`; quoting mistakes turning a description into a TOML boolean or array.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/c7b1beb43e1b5c4d. Report an issue: GitHub.