shareAI-lab/learn-claude-code · error · ValueError
Task subject cannot be empty
Error message
Task subject cannot be empty
What it means
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().
Source
Thrown at s10_task_system/code.py:104
return root
def _path(self, task_id: str, create_root: bool = False) -> Path:
if not isinstance(task_id, str) or not TASK_ID_PATTERN.fullmatch(task_id):
raise ValueError(f"Invalid task ID: {task_id!r}")
root = self._root(create=create_root)
path = (root / f"{task_id}.json").resolve()
if not path.is_relative_to(root):
raise ValueError(f"Invalid task ID: {task_id!r}")
return path
def exists(self, task_id: str) -> bool:
return self._path(task_id).is_file()
def create(self, subject: str, description: str = "",
blocked_by: list[str] | None = None) -> Task:
subject = subject.strip()
if not subject:
raise ValueError("Task subject cannot be empty")
dependencies = list(dict.fromkeys(blocked_by or []))
for dependency in dependencies:
if not self.exists(dependency):
raise ValueError(f"Dependency not found: {dependency}")
self._root(create=True)
for _ in range(100):
task = Task(
id=f"task_{secrets.token_hex(4)}",
subject=subject,
description=description,
status="pending",
owner=None,
blockedBy=dependencies,
)
try:
with self._path(task.id, create_root=True).open(View on GitHub (pinned to 985456f4ad)
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.
Example fix
# before
store.create(args.subject or '', description=args.description)
# after
subject = (args.subject or '').strip()
if not subject:
raise SystemExit('task subject is required')
store.create(subject, description=args.description) Defensive patterns
Strategy: validation
Validate before calling
def subject_ok(subject) -> bool:
return isinstance(subject, str) and bool(subject.strip()) Type guard
def is_task_subject(value) -> bool:
return isinstance(value, str) and len(value.strip()) > 0 Try / catch
try:
store.create(subject)
except ValueError as e:
if 'cannot be empty' in str(e):
raise SystemExit('a task subject is required')
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Memory name cannot be empty
- Memory description and body cannot be empty
- Invalid task ID: {task_id!r}
- Dependency not found: {dependency}
- Invalid task status: {task.status}
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/c96eaf559f30ca5a.
Report an issue: GitHub.