GitoxideLabs/gitoxide · error · anyhow::Error

a reference name has trailing data

Error message

a reference name has trailing data

What it means

Each reference item in a `(…)` line must consist solely of an ANSI-C-quoted name: `gix::quote::ansi_c::undo` returns how many bytes of the encoded item it consumed, and any non-whitespace bytes after that are rejected. `parse_ref_line` throws this error when there is trailing garbage after the name or its closing quote.

Solutions

  1. Delete the trailing text after the reference name (or after its closing quote).
  2. Separate additional names with commas: `(name1, name2)` instead of free text.
  3. Wrap characters requiring quoting in `"…"` and keep nothing outside the quotes.

Example fix

// before
(refs/heads/main keep this branch)

// after
(refs/heads/main)
Defensive patterns

Strategy: validation

Validate before calling

// Rust: each comma-separated item must be a single (optionally quoted) name
fn item_is_single_name(item: &str) -> bool {
    let item = item.trim().trim_start_matches('@');
    let bytes = item.as_bytes();
    if bytes.first() == Some(&b'"') {
        match item[1..].find('"') {
            Some(end) => item[end + 2..].trim().is_empty(),
            None => false,
        }
    } else {
        !item.is_empty() && !item.contains(char::is_whitespace)
    }
}

Try / catch

match parse_plan(&repo, text) {
    Ok(plan) => apply(plan),
    Err(e) if e.to_string().contains("trailing data") => {
        eprintln!("Remove text after the reference name; separate names with commas.");
        Err(e)
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `parse` with items like `"refs/heads/main" extra` or `refs/heads/main junk` where text follows the parseable quoted name.

Common situations: Notes or annotations typed after a reference name inside the parentheses; stray characters left by an editor; multiple names pasted without the separating comma (e.g. `"a""b"` plus trailing text).

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/4aeeee9882a8af7b. Report an issue: GitHub.

Appendix: source

Thrown at gix-tix/src/edit/todo.rs:1115

        }
    }
    if quoted || escaped {
        anyhow::bail!("a quoted reference name is not closed");
    }
    ranges.push(&body[start..]);
    let mut out = Vec::with_capacity(ranges.len());
    for item in ranges {
        let item = item.trim();
        if item.is_empty() {
            anyhow::bail!("a reference line contains an empty name");
        }
        let (marked, item) = item.strip_prefix('@').map_or((false, item), |item| (true, item));
        let encoded = item.as_bytes().as_bstr();
        let (name, consumed) = gix::quote::ansi_c::undo(encoded)
            .map_err(gix::Exn::into_error)
            .context("could not unquote a reference name")?;
        if !encoded[consumed..].trim().is_empty() {
            anyhow::bail!("a reference name has trailing data");
        }
        if name.is_empty() {
            anyhow::bail!("a reference name is empty");
        }
        out.push((marked, name.into_owned()));
    }
    Ok(out)
}

fn resolve_ref_name(
    repo: &gix::Repository,
    refs: &mut Vec<rebase::ExpectedRef>,
    input: &gix::bstr::BStr,
) -> Result<gix::refs::FullName> {
    let mut matches = refs
        .iter()
        .filter(|reference| reference.editable && ref_display_name(&reference.name, refs).as_bstr() == input)
        .map(|reference| reference.name.clone());

View on GitHub (pinned to e73179060b)