GitoxideLabs/gitoxide · error
a quoted reference name is not closed
Error message
a quoted reference name is not closed
What it means
`parse_ref_line` parses a `(name1, name2, …)` reference line with C-style quoting and backslash escapes. If, after scanning the whole body, the parser is still inside a quoted section or a pending escape (an odd number of `"` or a trailing `\`), it throws this error because the token stream is unterminated and names cannot be split reliably.
Solutions
- Add the missing closing `"` around the quoted reference name.
- Remove the dangling trailing `\` or double it (`\\`) if a literal backslash is intended.
- Avoid quoting altogether — plain, comma-separated reference names need no quotes.
Example fix
// before
("refs/heads/main, refs/tags/v1)
// after
("refs/heads/main", "refs/tags/v1") Defensive patterns
Strategy: validation
Validate before calling
// Rust: quick balance check for quotes/backslashes in a reference-line body
fn quotes_balanced(body: &str) -> bool {
let mut quoted = false;
let mut escaped = false;
for b in body.bytes() {
if escaped { escaped = false; continue; }
match b {
b'\\' if quoted => escaped = true,
b'"' => quoted = !quoted,
_ => {}
}
}
!quoted && !escaped
} Try / catch
match parse_plan(&repo, text) {
Ok(plan) => apply(plan),
Err(e) if e.to_string().contains("quoted reference name is not closed") => {
eprintln!("Fix unbalanced quotes/backslash in the (…) reference line.");
Err(e)
}
Err(e) => return Err(e),
} Prevention
- Keep reference names unquoted unless they contain spaces or special characters.
- Count your quotes: each `"` must be closed on the same line.
- Do not end a name with a lone backslash.
When it happens
Trigger: Calling `parse` with a reference line like `("refs/heads/main)` or `("branch ")` with a missing closing quote, or a name ending in a lone backslash `(refs/heads/main\)`.`
Common situations: Manual editing of the reference line drops a closing quote; a shell/editor eats a trailing backslash; quoting rules from other tools are copied in (e.g. single quotes, which this parser does not treat as quotes).
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
- a reference name has trailing data
- cannot find character that we didn't search for
- a reference line contains an empty name
- a reference name is empty
- BUG: tries to obtain object id from symbolic target
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/a64436ee5a9862be.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/todo.rs:1100
let mut quoted = false;
let mut escaped = false;
for (index, byte) in body.bytes().enumerate() {
if escaped {
escaped = false;
continue;
}
match byte {
b'\\' if quoted => escaped = true,
b'"' => quoted = !quoted,
b',' if !quoted => {
ranges.push(&body[start..index]);
start = index + 1;
}
_ => {}
}
}
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");View on GitHub (pinned to e73179060b)