{"record":{"id":"c96eaf559f30ca5a","repo":"shareAI-lab/learn-claude-code","slug":"task-subject-cannot-be-empty","errorCode":null,"errorMessage":"Task subject cannot be empty","messagePattern":"Task subject cannot be empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"s10_task_system/code.py","lineNumber":104,"sourceCode":"        return root\n\n    def _path(self, task_id: str, create_root: bool = False) -> 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        root = self._root(create=create_root)\n        path = (root / f\"{task_id}.json\").resolve()\n        if not path.is_relative_to(root):\n            raise ValueError(f\"Invalid task ID: {task_id!r}\")\n        return path\n\n    def exists(self, task_id: str) -> bool:\n        return self._path(task_id).is_file()\n\n    def create(self, subject: str, description: str = \"\",\n               blocked_by: list[str] | None = None) -> Task:\n        subject = subject.strip()\n        if not subject:\n            raise ValueError(\"Task subject cannot be empty\")\n\n        dependencies = list(dict.fromkeys(blocked_by or []))\n        for dependency in dependencies:\n            if not self.exists(dependency):\n                raise ValueError(f\"Dependency not found: {dependency}\")\n\n        self._root(create=True)\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 self._path(task.id, create_root=True).open(","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s10_task_system/code.py#L86-L122","documentation":"Raised by TaskStore.create() in s10_task_system/code.py:104 when the subject string is empty after strip(). The subject is the task's title and the only human-identifying field on the Task dataclass, so blank subjects are rejected before dependencies are checked or the store directory is created. Whitespace-only strings fail; None fails earlier with AttributeError on .strip().","triggerScenarios":"Calling store.create('   '), store.create(''), or passing a subject built from user/LLM input that reduces to empty after stripping (e.g. a form field left blank, an optional CLI argument defaulting to ''). Description and blocked_by may be empty — only the subject is checked.","commonSituations":"CLI tools where the subject argument is optional but passed unvalidated; agents creating tasks from parsed requests where the title extraction failed; automated pipelines forwarding empty strings as defaults.","solutions":["Validate subject.strip() before calling create() and prompt or skip when blank.","When deriving the subject from structured input, fall back to a generated summary (e.g. first line of the description) so it is never empty.","Fix the upstream producer to require a non-empty title."],"exampleFix":"# before\nstore.create(args.subject or '', description=args.description)\n\n# after\nsubject = (args.subject or '').strip()\nif not subject:\n    raise SystemExit('task subject is required')\nstore.create(subject, description=args.description)","handlingStrategy":"validation","validationCode":"def subject_ok(subject) -> bool:\n    return isinstance(subject, str) and bool(subject.strip())","typeGuard":"def is_task_subject(value) -> bool:\n    return isinstance(value, str) and len(value.strip()) > 0","tryCatchPattern":"try:\n    store.create(subject)\nexcept ValueError as e:\n    if 'cannot be empty' in str(e):\n        raise SystemExit('a task subject is required')\n    raise","preventionTips":["Make subject a required, validated input at the UI/CLI boundary.","Derive subjects from structured fields; fall back to a description summary when extraction is empty.","Test creation paths with whitespace-only subjects."],"tags":["validation","tasks","user-input"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}