abhigyanpatwari/GitNexus · error · ValueError
task id must be a simple artifact-safe slug: {task_id!r}
Error message
task id must be a simple artifact-safe slug: {task_id!r} What it means
Raised by select_tasks when the task id fails the artifact-safe slug regex `[A-Za-z0-9][A-Za-z0-9._-]{0,127}` (runner_tasks.py:44). The id is used downstream as a filename and JSON key, so it must start alnum, be 1–128 chars, and contain only alnum/./_-. No slashes, spaces, colons, or leading dots/dashes.
Source
Thrown at eval/workflow_bench/runner_tasks.py:45
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)
or set(dependency) != {"source", "target"}
or not all(isinstance(dependency[field], str) and dependency[field] for field in ("source", "target"))
):View on GitHub (pinned to d540b00184)
Solutions
- Rewrite the id to start with [A-Za-z0-9] and use only [A-Za-z0-9._-].
- Replace path separators and spaces with dashes.
- Shorten ids longer than 128 characters.
Example fix
# before - id: "tasks/refactor: cli" # after - id: "refactor-cli"
Defensive patterns
Strategy: validation
Validate before calling
import re
SLUG = re.compile(r"[A-Za-z0-9][A-Za-z0-9._-]{0,127}")
for t in doc.get("tasks", []):
if not SLUG.fullmatch(t.get("id", "")):
raise SystemExit(f"bad task id slug: {t.get('id')!r}") Type guard
def is_artifact_slug(value: str) -> bool:
import re
return bool(re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._-]{0,127}", value)) Prevention
- Name tasks with kebab-case slugs only.
- Never include slashes, spaces, colons, or leading dash/dot in ids.
- Cap id length at 128 characters.
When it happens
Trigger: An id containing a path separator (`tasks/foo`), a leading dash (`-task`), a space, a colon, unicode, or exceeding 128 chars. Also fires for ids that start with a dot or underscore (`_foo`, `.bar`).
Common situations: Naming a task after a repo path; using a human-readable title with spaces as the id; a generated id that prefixes with a dash.
Related errors
- task {index} requires a nonblank string {field}
- task {task['id']} field {field} must be a string
- duplicate task id: {task_id}
- 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/3877642e0914ff03.
Report an issue: GitHub.