{"record":{"id":"98188c2af20f1fd6","repo":"shareAI-lab/learn-claude-code","slug":"invalid-task-id-task-id-r-98188c","errorCode":null,"errorMessage":"Invalid task ID: {task_id!r}","messagePattern":"Invalid task ID: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"s13_agent_teams/code.py","lineNumber":125,"sourceCode":"        finally:\n            if team is not None:\n                team.release()\n\n\n@dataclass\nclass Task:\n    id: str\n    subject: str\n    description: str\n    status: str          # pending | in_progress | completed\n    owner: str | None\n    blockedBy: list[str]\n    worktree: str | None = None\n\n\ndef _task_path(task_id: str) -> Path:\n    if not isinstance(task_id, str) or not TASK_ID_PATTERN.fullmatch(task_id):\n        raise ValueError(f\"Invalid task ID: {task_id!r}\")\n    path = (TASKS_DIR / f\"{task_id}.json\").resolve()\n    if (not TASKS_ROOT.is_relative_to(WORKDIR.resolve())\n            or not path.is_relative_to(TASKS_ROOT)):\n        raise ValueError(f\"Invalid task ID: {task_id!r}\")\n    return path\n\n\ndef create_task(subject: str, description: str = \"\",\n                blockedBy: list[str] | None = None) -> Task:\n    subject = subject.strip()\n    if not subject:\n        raise ValueError(\"Task subject cannot be empty\")\n    dependencies = list(dict.fromkeys(blockedBy or []))\n    with task_store_lock():\n        for dependency in dependencies:\n            if not _task_path(dependency).is_file():\n                raise ValueError(f\"Dependency not found: {dependency}\")\n        for _ in range(100):","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s13_agent_teams/code.py#L107-L143","documentation":"Raised by _task_path() when a task ID fails the strict format TASK_ID_PATTERN = ^task_[0-9a-f]{8}$ (the literal prefix 'task_' plus exactly 8 lowercase hex characters, as generated by secrets.token_hex(4)). This is the single gatekeeper every task-file path passes through, so any API taking a task ID (load_task, get_task, can_start, etc.) rejects malformed IDs before touching the filesystem. It also fires for non-string input such as None or ints.","triggerScenarios":"Calling load_task('123'), load_task('task_ABCDEFGH') (uppercase), load_task('task_abc') (too short), load_task('task_deadbeefg') (9 chars), or load_task(None). Any ID not exactly matching task_ + 8 lowercase hex chars raises ValueError.","commonSituations":"Passing a database-style integer ID, a user-typed slug, an ID from a different system, or a copy-pasted ID with whitespace/typo. Also truncation or case-folding of generated IDs in transit.","solutions":["Use IDs returned by create_task() verbatim; they are always task_ + 8 hex chars.","If accepting external input, validate with the same regex ^task_[0-9a-f]{8}$ before calling task APIs.","Strip whitespace and lowercase the ID before validation, then re-check the pattern.","If you changed the ID scheme, keep TASK_ID_PATTERN in sync with the generator (secrets.token_hex length)."],"exampleFix":"// before\ntask = load_task(user_input)  # ValueError if user passes 'Task_AB12CD34'\n\n// after\nimport re\nTASK_ID_RE = re.compile(r'^task_[0-9a-f]{8}$')\ntask_id = user_input.strip().lower()\nif not TASK_ID_RE.fullmatch(task_id):\n    raise ValueError(f'Bad task id from user: {user_input!r}')\ntask = load_task(task_id)","handlingStrategy":"validation","validationCode":"import re\n\ndef is_valid_task_id(task_id) -> bool:\n    return isinstance(task_id, str) and re.fullmatch(r'task_[0-9a-f]{8}', task_id) is not None\n\n# before: load_task(user_id)\nif is_valid_task_id(user_id):\n    task = load_task(user_id)","typeGuard":"import re\nfrom typing import TypeGuard\n\n_TASK_ID_RE = re.compile(r'^task_[0-9a-f]{8}$')\n\ndef is_task_id(value: object) -> TypeGuard[str]:\n    return isinstance(value, str) and bool(_TASK_ID_RE.fullmatch(value))","tryCatchPattern":"try:\n    task = load_task(task_id)\nexcept ValueError as exc:\n    if 'Invalid task ID' in str(exc):\n        logger.warning('rejecting malformed task id %r', task_id)\n        return None\n    raise","preventionTips":["Treat task IDs as opaque tokens returned by create_task(); never construct them by hand.","Validate external input against ^task_[0-9a-f]{8}$ at the API boundary.","Lowercase and strip task IDs from user input before validation."],"tags":["validation","task-id","input-validation","file-path"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}