affaan-m/ECC · error
{stderr}
Error message
{stderr} What it means
Thrown by validate_branch_name at ecc2/src/worktree/mod.rs:1493 when `git check-ref-format --branch <branch>` fails AND git produced a non-empty stderr. Unlike the generic sibling (768), this branch trusts git's own diagnostic and re-emits it verbatim as the bail message. Common stderr texts include 'fatal: <name> is not a valid branch name' and refs/heads/ prefix collisions.
Source
Thrown at ecc2/src/worktree/mod.rs:1493
Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
}
fn validate_branch_name(repo_root: &Path, branch: &str) -> Result<()> {
let output = Command::new("git")
.arg("-C")
.arg(repo_root)
.args(["check-ref-format", "--branch", branch])
.output()
.context("Failed to validate worktree branch name")?;
if output.status.success() {
Ok(())
} else {
let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
if stderr.is_empty() {
anyhow::bail!("branch name is not a valid git ref");
} else {
anyhow::bail!("{stderr}");
}
}
}
fn parse_git_status_entry(line: &str) -> Option<GitStatusEntry> {
if line.len() < 4 {
return None;
}
let bytes = line.as_bytes();
let index_status = bytes[0] as char;
let worktree_status = bytes[1] as char;
let raw_path = line.get(3..)?.trim();
if raw_path.is_empty() {
return None;
}
let display_path = raw_path.to_string();
let normalized_path = raw_path
.split(" -> ")View on GitHub (pinned to 01e15490f0)
Solutions
- Read the forwarded stderr — it names the exact rule violated; address that specific rule (e.g. remove '~', '^', or ':').
- Avoid reserved names: HEAD, refs/heads/*, refs/tags/*, and names matching existing refs.
- Run `git check-ref-format --branch <name>` locally to see git's message before submitting.
- Sanitize with a slug function and re-validate in a loop until check-ref-format accepts the name.
Example fix
// before
let branch = user_name; // may contain '~', '^', ':'
validate_branch_name(&repo_root, &branch)?;
// after: iterate until git accepts the name
let mut candidate = user_name;
loop {
match validate_branch_name(&repo_root, &candidate) {
Ok(()) => break,
Err(e) => {
let next = candidate.chars().map(|c| match c {
'~'|'^'|':'|' '|'{'|'}' => '-',
_ => c,
}).collect::<String>();
if next == candidate { anyhow::bail!("unfixable branch name: {e}"); }
candidate = next;
}
}
} Defensive patterns
Strategy: validation
Validate before calling
fn git_accepts_branch(repo_root: &Path, name: &str) -> Result<bool> {
let out = Command::new("git").arg("-C").arg(repo_root)
.args(["check-ref-format", "--branch", name]).output()?;
Ok(out.status.success())
}
// surface git's specific complaint to the user instead of dropping it
if !git_accepts_branch(&repo_root, &branch)? {
let stderr = Command::new("git").arg("-C").arg(&repo_root)
.args(["check-ref-format", "--branch", &branch]).output()?;
let msg = String::from_utf8_lossy(&stderr.stderr).trim().to_string();
anyhow::bail!("branch rejected: {}", msg);
} Type guard
fn avoids_reserved_refs(s: &str) -> bool {
!s.eq_ignore_ascii_case("HEAD")
&& !s.starts_with("refs/heads/")
&& !s.starts_with("refs/tags/")
&& !s.contains('~') && !s.contains('^') && !s.contains(':')
} Try / catch
match validate_branch_name(&repo_root, &candidate) {
Ok(()) => Ok(candidate),
Err(e) => {
// e.to_string() is git's specific stderr — relay it verbatim to the user
let next = safe_branch_name(&candidate);
if next != candidate {
validate_branch_name(&repo_root, &next)?;
return Ok(next);
}
Err(e)
}
} Prevention
- Run check-ref-format in CI for every branch created from external input.
- Strip git-significant punctuation ('~', '^', ':', '@{', '..') in the slugifier.
- Avoid branch names that collide with tags or remote-tracking refs.
- Show git's verbatim stderr to the user so they can fix the specific rule violated.
When it happens
Trigger: Branch names that git can articulate a specific complaint about: 'refs/heads/..' style errors, locked refs, names that resolve to a different ref namespace, or names that git rejects because they would shadow an existing tag/ref via the --branch resolution path.
Common situations: Trying to name a branch 'HEAD' or 'refs/heads/main' (git complains about reserved names); names that collide with existing refs; version strings like 'v1.2.3' that also exist as tags; branch names containing '~', '^', ':' which check-ref-format flags explicitly.
Related errors
- branch name is not a valid git ref
- Unable to infer ECC repo root from install-state operations
- Project memory .gitignore does not contain the required fail
- selected hunk is already staged
- selected hunk is not staged
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/1803808d7b43da04.
Report an issue: GitHub.