{"record":{"id":"ec322e9ff1eab0c7","repo":"shareAI-lab/learn-claude-code","slug":"task-subject-cannot-be-empty-ec322e","errorCode":null,"errorMessage":"Task subject cannot be empty","messagePattern":"Task subject cannot be empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"s13_agent_teams/code.py","lineNumber":137,"sourceCode":"    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):\n            task = Task(\n                id=f\"task_{secrets.token_hex(4)}\",\n                subject=subject,\n                description=description,\n                status=\"pending\",\n                owner=None,\n                blockedBy=dependencies,\n            )\n            try:\n                with _task_path(task.id).open(\"x\", encoding=\"utf-8\") as handle:\n                    json.dump(asdict(task), handle, indent=2)\n                return task","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s13_agent_teams/code.py#L119-L155","documentation":"create_task() strips the subject and raises ValueError when the result is empty. A task must have a non-empty human-readable subject; this is the earliest of create_task's three validation gates (subject, dependency existence, ID allocation).","triggerScenarios":"create_task(''), create_task('   ') (whitespace-only — it is stripped first), or passing a subject that is None-adjacent glue like f\"{missing_var}\" producing ''.","commonSituations":"Building subjects from optional template variables that are empty, forwarding unvalidated form input, or programmatic task generation where a list field was empty.","solutions":["Check subject.strip() before calling create_task and supply a real title.","If generating tasks in a loop, skip/log entries whose subject is blank instead of calling.","Default missing subjects to a generated name like f'Task {date}' rather than ''."],"exampleFix":"// before\ntask = create_task(subject or '')  // ValueError\n\n// after\nif not (subject or '').strip():\n    raise ValueError('subject required')\ntask = create_task(subject)","handlingStrategy":"validation","validationCode":"def valid_subject(subject: str) -> bool:\n    return isinstance(subject, str) and bool(subject.strip())","typeGuard":"from typing import TypeGuard\n\ndef is_nonempty_subject(value: object) -> TypeGuard[str]:\n    return isinstance(value, str) and len(value.strip()) > 0","tryCatchPattern":null,"preventionTips":["Validate subject.strip() in UI/forms before calling create_task.","When templating subjects from optional data, assert the result is non-empty."],"tags":["validation","create-task","input-validation"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}