shareAI-lab/learn-claude-code · error · ValueError
Task subject cannot be empty
Error message
Task subject cannot be empty
What it means
create_task() strips the subject and refuses to create a task with an empty subject. The subject is the task's primary identifier shown in listings and to teammate agents, so blank subjects are rejected outright rather than defaulted.
Solutions
- Pass a non-empty, meaningful subject string (it is .strip()ed, so trim whitespace first if you need exact content).
- If automating, fall back to a derived subject (e.g. first line of description) instead of an empty string.
- Validate subject.strip() on the caller side before invoking the tool.
Example fix
// before create_task(subject="", description="fix login bug") // after create_task(subject="Fix login bug", description="fix login bug")
Defensive patterns
Strategy: validation
Validate before calling
subject = subject.strip() if isinstance(subject, str) else ""
if not subject:
subject = description.strip().splitlines()[0] if description.strip() else None
if subject:
task = create_task(subject, description) Type guard
def is_valid_subject(subject) -> bool:
return isinstance(subject, str) and bool(subject.strip()) Try / catch
try:
create_task(subject, description)
except ValueError as e:
if "subject cannot be empty" in str(e):
# prompt the caller/model for a subject; do not default silently
raise Prevention
- Require a non-empty subject in UI/tool schemas (minLength: 1).
- Strip input before submission.
- When automating from descriptions, derive subject from the first line.
When it happens
Trigger: Calling create_task(subject="" ), create_task(" "), or passing a subject that is only whitespace. Common when the argument comes from an LLM tool call where the model put the subject in the wrong parameter or omitted it.
Common situations: Model fills description but leaves subject blank; a script maps the wrong column/field into subject; whitespace-padded input from a form or CSV.
Related errors
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/c2ea5e6ab847d92e.
Report an issue: GitHub.
Appendix: source
Thrown at s15_integrated_harness/code.py:212
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):
task = Task(
id=f"task_{secrets.token_hex(4)}",
subject=subject,
description=description,
status="pending",
owner=None,
blockedBy=dependencies,
)
try:
with _task_path(task.id).open("x", encoding="utf-8") as handle:
json.dump(asdict(task), handle, indent=2)
return taskView on GitHub (pinned to 985456f4ad)