shareAI-lab/learn-claude-code · error · ValueError
Invalid task ID: {task_id!r}
Error message
Invalid task ID: {task_id!r} What it means
_task_path() validates a task ID before mapping it to a file under the tasks directory. This first raise fires when task_id is not a str or fails TASK_ID_PATTERN.fullmatch — i.e. the ID is malformed (wrong shape, bad characters) before any filesystem resolution happens. All task APIs (create/load/save/get_task_json/can_start) funnel through this guard.
Source
Thrown at s15_integrated_harness/code.py:200
finally:
if team is not None:
team.release()
@dataclass
class Task:
id: str
subject: str
description: str
status: str
owner: str | None
blockedBy: list[str]
worktree: str | None = None
def _task_path(task_id: str) -> Path:
if not isinstance(task_id, str) or not TASK_ID_PATTERN.fullmatch(task_id):
raise ValueError(f"Invalid task ID: {task_id!r}")
path = (TASKS_DIR / f"{task_id}.json").resolve()
if (not TASKS_ROOT.is_relative_to(WORKDIR.resolve())
or not path.is_relative_to(TASKS_ROOT)):
raise ValueError(f"Invalid task ID: {task_id!r}")
return path
def create_task(subject: str, description: str = "",
blockedBy: list[str] | None = None) -> Task:
subject = subject.strip()
if not subject:
raise ValueError("Task subject cannot be empty")
dependencies = list(dict.fromkeys(blockedBy or []))
with task_store_lock():
for dependency in dependencies:
if not _task_path(dependency).is_file():
raise ValueError(f"Dependency not found: {dependency}")
for _ in range(100):View on GitHub (pinned to 985456f4ad)
Solutions
- Generate IDs only via create_task() (format task_ + 8 hex chars, e.g. task_1a2b3c4d) and pass those verbatim.
- Sanitize caller input against the same pattern (regex like r'task_[0-9a-f]{8}') before invoking task APIs.
- If you changed TASK_ID_PATTERN, regenerate/rewrite existing task JSON filenames to match.
Example fix
// before
load_task(user_supplied_id) // raises ValueError: Invalid task ID
// after
import re
TASK_ID_RE = re.compile(r"task_[0-9a-f]{8}")
if not isinstance(user_supplied_id, str) or not TASK_ID_RE.fullmatch(user_supplied_id):
return f"Error: malformed task ID {user_supplied_id!r}"
task = load_task(user_supplied_id) Defensive patterns
Strategy: validation
Validate before calling
import re
TASK_ID_RE = re.compile(r"task_[0-9a-f]{8}")
def is_valid_task_id(task_id) -> bool:
return isinstance(task_id, str) and bool(TASK_ID_RE.fullmatch(task_id)) Type guard
def is_task_id(value) -> bool:
return isinstance(value, str) and bool(__import__('re').fullmatch(r'task_[0-9a-f]{8}', value)) Try / catch
try:
task = load_task(task_id)
except ValueError as e:
if "Invalid task ID" in str(e):
return f"Error: {e}" # surface to model/user, do not retry
raise Prevention
- Only use IDs returned by create_task().
- Validate IDs against task_[0-9a-f]{8} before calling task APIs.
- Never accept task IDs verbatim from freeform model text without a regex check.
When it happens
Trigger: Calling load_task/save_task/create_task dependencies with values like None, an int, 'task_abc' not matching the pattern, IDs containing slashes or '../', or empty strings. Also model-generated tool calls passing unvalidated IDs from conversation text.
Common situations: An LLM tool call hallucinating a task ID format; passing a file stem with whitespace; passing a Path object instead of str; IDs from an older format after the pattern was tightened.
Related errors
- Invalid task ID: {task_id!r}
- Task subject cannot be empty
- Task subject cannot be empty
- Max 20 todos allowed
- Item {item_id}: text required
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/3b9b0d1c4b3512b9.
Report an issue: GitHub.