abhigyanpatwari/GitNexus · error · ValueError
task {task['id']} field {field} must be a string
Error message
task {task['id']} field {field} must be a string What it means
Raised by select_tasks after the required-string check passes. The optional fields ref and setup (optional_strings at runner_tasks.py:32) must be strings if present. Unlike the required fields, blank/whitespace-only is permitted here — only the str type is enforced.
Source
Thrown at eval/workflow_bench/runner_tasks.py:42
def select_tasks(tasks: list[Any], *, include_expensive: bool) -> tuple[list[dict[str, Any]], list[str]]:
"""Validate task metadata and filter opt-in expensive scenarios."""
selected: list[dict[str, Any]] = []
skipped: list[str] = []
seen: set[str] = set()
required_strings = ("id", "class", "repo", "prompt", "verify")
optional_strings = ("ref", "setup")
for index, raw_task in enumerate(tasks):
if not isinstance(raw_task, Mapping):
raise ValueError(f"task {index} must be a mapping")
task = dict(raw_task)
for field in required_strings:
if not isinstance(task.get(field), str) or not task[field].strip():
raise ValueError(f"task {index} requires a nonblank string {field}")
for field in optional_strings:
if field in task and not isinstance(task[field], str):
raise ValueError(f"task {task['id']} field {field} must be a string")
task_id = task["id"]
if not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._-]{0,127}", task_id):
raise ValueError(f"task id must be a simple artifact-safe slug: {task_id!r}")
if task_id in seen:
raise ValueError(f"duplicate task id: {task_id}")
seen.add(task_id)
expensive = task.get("expensive", False)
if not isinstance(expensive, bool):
raise ValueError(f"task {task_id} expensive metadata must be boolean")
copies = task.get("sandbox_copy", [])
if not isinstance(copies, list) or not all(isinstance(path, str) and path for path in copies):
raise ValueError(f"task {task_id} sandbox_copy must be a string list")
dependencies = task.get("sandbox_dependencies", [])
if not isinstance(dependencies, list):
raise ValueError(f"task {task_id} sandbox_dependencies must be a list")
for dependency in dependencies:
if (
not isinstance(dependency, Mapping)View on GitHub (pinned to d540b00184)
Solutions
- Inspect the offending task's ref/setup value and confirm it is a scalar string.
- If you need no ref/setup, remove the key entirely rather than leaving it null.
- Quote the value in YAML to avoid implicit type coercion.
Example fix
# before
- id: t1
ref:
- main
# after
- id: t1
ref: main Defensive patterns
Strategy: type-guard
Validate before calling
OPTIONAL = ("ref", "setup")
for i, t in enumerate(doc.get("tasks", [])):
for f in OPTIONAL:
if f in t and not isinstance(t[f], str):
raise SystemExit(f"task {i} field {f} must be a string") Type guard
def optional_fields_are_strings(task: dict) -> bool:
return all(
f not in task or isinstance(task[f], str)
for f in ("ref", "setup")
) Prevention
- Omit ref/setup when unused rather than leaving null.
- Quote scalar values in YAML to avoid implicit non-string coercion.
When it happens
Trigger: A task sets ref to a YAML list (e.g. a multi-line block folded wrong) or to a number, or sets setup to null/mapping. The check is `field in task and not isinstance(task[field], str)`.
Common situations: Writing `ref: HEAD` works but `ref: [HEAD]` does not; `setup:` with no value yields None and trips it; an automated task generator emitting setup as an object.
Related errors
- task {index} requires a nonblank string {field}
- task {task_id} expensive metadata must be boolean
- task {task_id} sandbox_copy must be a string list
- task {task_id} sandbox_dependencies must be a list
- task id must be a simple artifact-safe slug: {task_id!r}
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/5863e037f144d0ab.
Report an issue: GitHub.