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
- 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
- Fill in a meaningful non-empty string at that location, or restore the file with `git checkout -- python/robomp/src/prompts/<file>.toml`
- Keep parameter names in `host_tools.toml` in sync with the Python tool definitions after renames
- 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
- Add a startup pass asserting every tool has a non-empty description and every parameter a non-empty description
- Unit-test that host_tools.toml keys match the registered host tools to catch renames/drift
- Avoid empty or whitespace placeholder strings when drafting entries
- Re-validate prompt data files after merges before deploying
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
- prompt data file {name!r} must contain a TOML table
- {context} must be a table
- todo_phases.toml[{task_kind!r}] must be a list of phases
- OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains an empty provider
- OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains a provider id wit
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/c7b1beb43e1b5c4d.
Report an issue: GitHub.