shareAI-lab/learn-claude-code · error · ValueError
Invalid worktree name. Use 1-40 chars: letters, numbers, .,
Error message
Invalid worktree name. Use 1-40 chars: letters, numbers, ., _, -
What it means
Thrown by WorktreeManager._validate_name when creating a worktree whose name fails the regex [A-Za-z0-9._-]{1,40}. The name is used both as a directory name under the worktree dir and inside the branch name wt/{name}, so any character outside that whitelist (spaces, slashes, unicode) or a name longer than 40 chars (or empty/None) is rejected before any git command runs. This is a fail-fast input validation guard, not a git failure.
Source
Thrown at agents/s12_worktree_task_isolation.py:280
raise RuntimeError(msg or f"git {' '.join(args)} failed")
return (r.stdout + r.stderr).strip() or "(no output)"
def _load_index(self) -> dict:
return json.loads(self.index_path.read_text())
def _save_index(self, data: dict):
self.index_path.write_text(json.dumps(data, indent=2))
def _find(self, name: str) -> dict | None:
idx = self._load_index()
for wt in idx.get("worktrees", []):
if wt.get("name") == name:
return wt
return None
def _validate_name(self, name: str):
if not re.fullmatch(r"[A-Za-z0-9._-]{1,40}", name or ""):
raise ValueError(
"Invalid worktree name. Use 1-40 chars: letters, numbers, ., _, -"
)
def create(self, name: str, task_id: int = None, base_ref: str = "HEAD") -> str:
self._validate_name(name)
if self._find(name):
raise ValueError(f"Worktree '{name}' already exists in index")
if task_id is not None and not self.tasks.exists(task_id):
raise ValueError(f"Task {task_id} not found")
path = self.dir / name
branch = f"wt/{name}"
self.events.emit(
"worktree.create.before",
task={"id": task_id} if task_id is not None else {},
worktree={"name": name, "base_ref": base_ref},
)
try:View on GitHub (pinned to 985456f4ad)
Solutions
- Sanitize the name before calling create(): lower-case it and re.sub(r'[^A-Za-z0-9._-]+', '-', name), then trim to 40 chars
- Strip whitespace around the name and reject empty results before calling the manager
- Replace '/' in derived names (e.g. from branch paths) with '-' so the wt/{name} branch stays well-formed
- Catch ValueError at the tool boundary and surface it back to the caller so the agent can retry with a cleaned name
Example fix
// before
wt.create(name="Fix login bug / session", task_id=7)
// after
import re
name = re.sub(r'[^A-Za-z0-9._-]+', '-', "Fix login bug / session").strip('-.')[:40]
wt.create(name=name, task_id=7) Defensive patterns
Strategy: validation
Validate before calling
import re
def valid_worktree_name(name: str) -> bool:
return bool(re.fullmatch(r"[A-Za-z0-9._-]{1,40}", name or ""))
# before create():
assert valid_worktree_name(name), "name must be 1-40 chars of [A-Za-z0-9._-]" Type guard
def is_valid_worktree_name(name: object) -> bool:
return isinstance(name, str) and bool(__import__('re').fullmatch(r"[A-Za-z0-9._-]{1,40}", name)) Try / catch
try:
path = wt.create(name, task_id=tid)
except ValueError as e:
if 'Invalid worktree name' in str(e):
name = re.sub(r'[^A-Za-z0-9._-]+', '-', name).strip('-.')[:40]
path = wt.create(name, task_id=tid)
else:
raise Prevention
- Sanitize derived names (task subjects, branch names) with a slug function before create()
- Strip and reject empty names client-side
- Never let free-form LLM output reach create() unfiltered
When it happens
Trigger: Calling worktree create with name="my task" (space), name="feature/fix" (slash), name="задача" (unicode), name="" or None, or a name of 41+ characters. The regex uses fullmatch, so even a trailing newline embedded in the string fails.
Common situations: Agent pipelines auto-deriving worktree names from free-form task subjects or ticket titles without sanitizing; names containing '/' that would also collide with the wt/{name} branch namespace; trailing whitespace from user input not being stripped before the call.
Related errors
- Task {task_id} not found
- Invalid status: {status}
- Not in a git repository. worktree tools require git.
- git {' '.join(args)} failed
- Worktree '{name}' already exists in index
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/e366c2264e5d6518.
Report an issue: GitHub.