{"record":{"id":"3aaa805e8450e7e0","repo":"gitbutlerapp/gitbutler","slug":"cannot-derive-a-worktree-directory-from","errorCode":null,"errorMessage":"Cannot derive a worktree directory from '{}'","messagePattern":"Cannot derive a worktree directory from '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-api/src/worktrees.rs","lineNumber":343,"sourceCode":"    worktree_new_at_base_with_perm(ctx, new_ref, base, perm)\n}\n\n/// Create a worktree at a given base.\npub fn worktree_new_at_base_with_perm(\n    ctx: &but_ctx::Context,\n    new_ref: Option<gix::refs::FullName>,\n    base: gix::ObjectId,\n    perm: &mut RepoExclusive,\n) -> Result<NewWorktree> {\n    ensure_worktree_manipulation_enabled(ctx)?;\n    let (repo, ws, db) = ctx.workspace_and_db_with_perm(perm.read_permission())?;\n    let ref_name = match new_ref {\n        Some(ref_name) => ref_name,\n        None => unique_canned_refname(&repo)?,\n    };\n    let slug = slug(ref_name.shorten());\n    if slug.is_empty() {\n        bail!(\n            \"Cannot derive a worktree directory from '{}'\",\n            ref_name.shorten()\n        );\n    }\n    let path = repo.common_dir().join(\"gb-wts\").join(&slug);\n    let name = but_workspace::worktrees::add(&repo, &path, ref_name.as_ref(), base)?;\n    let path = gix::path::realpath(&path)?;\n    drop((repo, ws, db));\n    ctx.invalidate_workspace_cache()?;\n    Ok(NewWorktree {\n        name,\n        path,\n        ref_name,\n        base,\n    })\n}\n\n/// Turn `name` into a single lowercase ASCII path component, keeping letters and digits and","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-api/src/worktrees.rs#L325-L361","documentation":"This error is thrown when creating a new worktree at a base commit but the reference name for the worktree cannot be turned into a non-empty directory slug. The library derives the worktree directory name from the ref's short name via slug(); if the resulting slug is empty, there is no usable directory name and it bails. Typically this happens when no explicit ref is provided and unique_canned_refname() produced a name whose shortened form slugs to empty.","triggerScenarios":"Calling worktree_new_with_perm / worktree_new_at_base_with_perm without an explicit new_ref so a generated refname is used, and slug(ref_name.shorten()) returns \"\" — e.g. the shortened ref consists only of characters stripped by slug().","commonSituations":"Programmatic callers passing unusual or empty ref names; a refname generator yielding names with only slash/special characters; locales or edge-case branch names that normalize away entirely.","solutions":["Pass an explicit new_ref with a normal branch name (letters/digits/hyphens) when calling worktree_new_at_base_with_perm","Inspect the ref name being generated (unique_canned_refname) and fix or sanitize it so its shortened form yields a non-empty slug","Add a pre-call check that slug(ref_name.shorten()) is non-empty"],"exampleFix":"// before\nworktree_new_at_base_with_perm(..., None, ...)?;\n// after\nworktree_new_at_base_with_perm(..., Some(gix::refs::PartialName::from(\"my-feature\")), ...)?;","handlingStrategy":"validation","validationCode":"let slug = slug(ref_name.shorten());\nif slug.is_empty() {\n    return Err(anyhow::anyhow!(\"ref '{}' yields empty worktree slug\", ref_name.shorten()));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass an explicit, well-formed ref name when creating worktrees programmatically","Sanitize branch names (strip special characters) before deriving directory names","Unit-test the slug function against unusual ref names"],"tags":["rust","worktree","slug","invalid-argument"],"backgroundTag":"invalid-argument-value","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}