{"record":{"id":"e9aa752b213a2377","repo":"can1357/oh-my-pi","slug":"prompt-data-file-name-r-must-contain-a-toml-tabl","errorCode":null,"errorMessage":"prompt data file {name!r} must contain a TOML table","messagePattern":"prompt data file (.+?) must contain a TOML table","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/robomp/src/persona.py","lineNumber":56,"sourceCode":"    if isinstance(value, (list, tuple)):\n        return \", \".join(str(item) for item in value)\n    return str(value)\n\n\ndef render(template: str, scope: Mapping[str, Any]) -> str:\n    return _PLACEHOLDER.sub(lambda m: _lookup(m.group(1), scope), template)\n\n\n@cache\ndef _load(name: str) -> str:\n    return resources.files(\"robomp.prompts\").joinpath(name).read_text(encoding=\"utf-8\")\n\n\n@cache\ndef _load_toml(name: str) -> Mapping[str, Any]:\n    data = tomllib.loads(_load(name))\n    if not isinstance(data, Mapping):\n        raise ValueError(f\"prompt data file {name!r} must contain a TOML table\")\n    return data\n\n\ndef _require_mapping(value: Any, context: str) -> Mapping[str, Any]:\n    if not isinstance(value, Mapping):\n        raise ValueError(f\"{context} must be a table\")\n    return value\n\n\ndef _require_nonempty_str(value: Any, context: str) -> str:\n    if not isinstance(value, str) or not value.strip():\n        raise ValueError(f\"{context} must be a non-empty string\")\n    return value\n\n\ndef seed_phases(task_kind: str) -> list[dict[str, Any]]:\n    raw_phases = _load_toml(\"todo_phases.toml\").get(task_kind, [])\n    if not isinstance(raw_phases, list):","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/robomp/src/persona.py#L38-L74","documentation":"`_load_toml(name)` reads a package-data file from `robomp.prompts`, parses it with `tomllib`, and requires the parsed document to be a TOML table (Mapping). If the top-level document parses to a non-table — a bare string, array, or number, all valid TOML — a ValueError is raised, because every caller indexes into the result with `.get()`.","triggerScenarios":"Calling `seed_phases(task_kind)` or `_host_tool_entry(tool_name)` (indirectly `host_tool_description`, `host_tool_parameter_description`, `classify_next_step`) when `todo_phases.toml` or `host_tools.toml` in `python/robomp/src/prompts/` starts with a bare TOML value or contains only array-of-tables (`[[...]]`) with no top-level table header, so `tomllib.loads` returns a list instead of a dict.","commonSituations":"Editing a prompt data file and deleting the `[todo_phases.<kind>]` / `[<tool>]` table headers; a bad merge leaving the file as a bare array; reformatting the file with a tool that emits a top-level array; shipping a file whose first non-comment line is a lone literal.","solutions":["Open the offending .toml in `python/robomp/src/prompts/` and ensure the top level is a table: wrap content under explicit headers like `[todo_phases.bug]` or `[create_pr]`","Restore a clobbered file with `git checkout -- python/robomp/src/prompts/<name>.toml` if a merge broke it","Validate: `python -c \"import tomllib; print(type(tomllib.load(open('<path>','rb'))))\"` must print `<class 'dict'>`","Restart the process after fixing — `_load_toml` is `@cache`d, so edits are not picked up mid-process"],"exampleFix":"# before (todo_phases.toml)\n[[phase]]\nname = \"reproduce\"\n\n# after\n[todo_phases]\nbug = [{ name = \"reproduce\", tasks = [\"write repro\", \"confirm failure\"] }]","handlingStrategy":"validation","validationCode":"import tomllib\ndata = tomllib.load(open(\"python/robomp/src/prompts/todo_phases.toml\", \"rb\"))\nassert isinstance(data, dict), \"TOML top level must be a table\"","typeGuard":"def is_table(value) -> bool:\n    import collections.abc\n    return isinstance(value, collections.abc.Mapping)","tryCatchPattern":"try:\n    phases = seed_phases(task_kind)\nexcept ValueError as e:\n    logger.error(\"prompt data TOML malformed: %s\", e)\n    raise  # fail fast at startup; prompt data errors should not be swallowed","preventionTips":["Always start prompt data .toml files with an explicit top-level table header","Run a startup-time validation that parses every file in robomp/prompts/ and asserts a dict top level","Fail fast at service startup by calling seed_phases/host_tool_description once during init","Restart the process after editing TOML files — they are cached with @cache"],"tags":["toml","configuration","validation","prompt-data"],"backgroundTag":"toml-schema-validation-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}