abhigyanpatwari/GitNexus · error · ValueError
duplicate task id: {task_id}
Error message
duplicate task id: {task_id} What it means
Raised by select_tasks when a task id has already been added to the `seen` set during the same pass (runner_tasks.py:46-47). Ids must be unique because they key the bindings JSONL, the results aggregation, and the per-task output paths.
Source
Thrown at eval/workflow_bench/runner_tasks.py:47
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)
or set(dependency) != {"source", "target"}
or not all(isinstance(dependency[field], str) and dependency[field] for field in ("source", "target"))
):
raise ValueError(
f"task {task_id} sandbox_dependencies entries require nonblank source and target strings"View on GitHub (pinned to d540b00184)
Solutions
- Search the tasks file for the duplicated id and give each occurrence a distinct slug.
- Use `yq '.tasks[].id' tasks.yaml | sort | uniq -d` to list all duplicate ids at once.
- Re-run after renaming.
Example fix
# before - id: baseline prompt: A - id: baseline prompt: B # after - id: baseline-a prompt: A - id: baseline-b prompt: B
Defensive patterns
Strategy: validation
Validate before calling
ids = [t.get("id") for t in doc.get("tasks", [])]
dups = {i for i in ids if ids.count(i) > 1}
if dups:
raise SystemExit(f"duplicate task ids: {sorted(dups)}") Type guard
def ids_are_unique(tasks: list[dict]) -> bool:
ids = [t.get("id") for t in tasks]
return len(ids) == len(set(ids)) Prevention
- Run `yq '.tasks[].id' tasks.yaml | sort | uniq -d` before committing.
- Generate ids from a single source of truth to avoid collisions when merging task files.
When it happens
Trigger: Two task mappings share the same id string; copy-pasting a task block and forgetting to rename the id.
Common situations: Duplicating a task to vary only the prompt/ref but leaving the id; merging two YAML task files that both define `baseline`.
Related errors
- task {index} requires a nonblank string {field}
- task {task['id']} field {field} must be a string
- task id must be a simple artifact-safe slug: {task_id!r}
- task {task_id} expensive metadata must be boolean
- task {task_id} sandbox_copy must be a string list
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/86beee81d4d73523.
Report an issue: GitHub.