{"record":{"id":"c06ef52273452f97","repo":"Hmbown/CodeWhale","slug":"worktree-branch-must-not-be-empty","errorCode":null,"errorMessage":"worktree branch must not be empty","messagePattern":"worktree branch must not be empty","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/lane/src/worktree.rs","lineNumber":33,"sourceCode":"    pub repo_root: PathBuf,\n    /// Branch to create (from `base_ref`).\n    pub branch: String,\n    /// Directory for the new worktree (created by `git worktree add`).\n    pub path: PathBuf,\n    /// Base ref to branch from (default `HEAD`).\n    pub base_ref: Option<String>,\n}\n\n#[derive(Debug, Clone)]\npub struct ProvisionedWorktree {\n    pub path: PathBuf,\n    pub branch: String,\n}\n\n/// Create a git worktree + branch for a lane.\npub fn provision_worktree(spec: &WorktreeProvision) -> Result<ProvisionedWorktree> {\n    if spec.branch.trim().is_empty() {\n        bail!(\"worktree branch must not be empty\");\n    }\n    if !spec.repo_root.exists() {\n        bail!(\"repo root does not exist: {}\", spec.repo_root.display());\n    }\n    if let Some(parent) = spec.path.parent() {\n        fs::create_dir_all(parent)\n            .with_context(|| format!(\"create worktree parent {}\", parent.display()))?;\n    }\n    let base = spec.base_ref.as_deref().unwrap_or(\"HEAD\");\n    // Capture git output instead of inheriting the caller's terminal. Runtime\n    // callers include the raw-mode TUI launch screen, where even one inherited\n    // progress/error line corrupts the alternate-screen buffer.\n    let output = Command::new(\"git\")\n        .current_dir(&spec.repo_root)\n        .args([\n            \"worktree\",\n            \"add\",\n            \"-b\",","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/lane/src/worktree.rs#L15-L51","documentation":"provision_worktree validates its spec before touching git: a branch name that is empty after trimming bails immediately (the repo-root existence check follows). The branch becomes a real `git worktree add` argument and a ref name, and git rejects empty/whitespace branch names with worse diagnostics, so the guard fails fast with an actionable message.","triggerScenarios":"Calling provision_worktree with spec.branch = \"\", \"   \", or a value that only looks present (e.g. built from an empty option or an id that failed to generate). Whitespace-only names are caught because the check uses trim().","commonSituations":"Branch names derived from user input or lane titles that were blank; formatting bugs producing empty strings (format! with missing args); Option fields defaulted to empty instead of None; copy-paste configs with an uncommented empty branch key.","solutions":["Supply a real branch name (e.g. lanes/<lane-id>) in the WorktreeProvision spec","Default the branch when the caller has none: format!(\"lane-{lane_id}\")","Validate trimmed non-emptiness where you build the spec so failure surfaces at the source"],"exampleFix":"// before\nlet spec = WorktreeProvision { branch: title.clone(), .. }; // title may be blank\n\n// after\nlet branch = if title.trim().is_empty() {\n    format!(\"lane-{lane_id}\")\n} else {\n    title.trim().to_string()\n};\nlet spec = WorktreeProvision { branch, .. };","handlingStrategy":"validation","validationCode":"anyhow::ensure!(!spec.branch.trim().is_empty(), \"worktree branch must not be empty\");","typeGuard":"fn branch_name_valid(branch: &str) -> bool {\n    !branch.trim().is_empty() && !branch.contains(\"..\") && !branch.starts_with('-')\n}","tryCatchPattern":null,"preventionTips":["Default branch names deterministically (format!(\"lane-{lane_id}\")) instead of passing user text through","Trim and reject blank branch fields at config load time","Represent 'no branch chosen' as None in the spec, never as an empty string"],"tags":["rust","lane","worktree","git","validation","empty-argument"],"backgroundTag":"empty-required-field","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}