{"record":{"id":"48785cf924649866","repo":"GitoxideLabs/gitoxide","slug":"the-recorded-head-ref-has-trailing-data","errorCode":null,"errorMessage":"the recorded HEAD ref has trailing data","messagePattern":"the recorded HEAD ref has trailing data","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-tix/src/edit/todo.rs","lineNumber":711,"sourceCode":"            \"tip\" => tips.push(ObjectId::from_hex(value.as_bytes())?),\n            \"scope\" => scope.push(ObjectId::from_hex(value.as_bytes())?),\n            \"marker-required\" => {\n                if marker_required.replace(value.parse()?).is_some() {\n                    anyhow::bail!(\"the rebase state repeats marker-required\");\n                }\n            }\n            \"checkout-allowed\" => {\n                if checkout_allowed.replace(value.parse()?).is_some() {\n                    anyhow::bail!(\"the rebase state repeats checkout-allowed\");\n                }\n            }\n            \"head-ref\" => {\n                let encoded = value.as_bytes().as_bstr();\n                let (name, consumed) = gix::quote::ansi_c::undo(encoded)\n                    .map_err(gix::Exn::into_error)\n                    .context(\"could not unquote the recorded HEAD ref\")?;\n                if !encoded[consumed..].trim().is_empty() {\n                    anyhow::bail!(\"the recorded HEAD ref has trailing data\");\n                }\n                let name = gix::refs::FullName::try_from(name.as_ref()).context(\"the recorded HEAD ref is invalid\")?;\n                if head_ref.replace(name).is_some() {\n                    anyhow::bail!(\"the rebase state repeats its HEAD ref\");\n                }\n            }\n            \"edit-refs\" => edit_refs = value.parse()?,\n            \"ref\" => {\n                let (old, value) = value.split_once(' ').context(\"a captured ref has no target\")?;\n                let (target, value) = value.split_once(' ').context(\"a captured ref has no follow mode\")?;\n                let old = (old != \"-\").then(|| ObjectId::from_hex(old.as_bytes())).transpose()?;\n                let target = ObjectId::from_hex(target.as_bytes())?;\n                let (follows_tip, value) = value.split_once(' ').context(\"a captured ref has no name\")?;\n                let follows_tip = follows_tip.parse()?;\n                let (editable, name) = value\n                    .split_once(' ')\n                    .and_then(|(editable, name)| editable.parse::<bool>().ok().map(|editable| (editable, name)))\n                    .unwrap_or((false, value));","sourceCodeStart":693,"sourceCodeEnd":729,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tix/src/edit/todo.rs#L693-L729","documentation":"After unquoting the `head-ref` value with `gix::quote::ansi_c::undo`, the parser checks that nothing meaningful remains after the quoted reference name (`encoded[consumed..].trim()`). Trailing data after the ref name means the `head-ref` line is malformed, so parsing aborts. This catches corrupted or hand-mangled ref entries before they are turned into a `gix::refs::FullName`.","triggerScenarios":"`parse_state` (gix-tix/src/edit/todo.rs:711) sees a `head-ref` line whose value contains extra tokens after the (possibly C-quoted) ref name, e.g. `head-ref \"refs/heads/main\" extra` or `head-ref refs/heads/main garbage`.","commonSituations":"Manual edits leaving stray characters; copy-paste of ref lines with extra whitespace-separated tokens; corruption from interrupted writes; older/newer state formats that included extra data.","solutions":["Edit the `head-ref` line so it contains exactly one (optionally C-quoted) fully-qualified ref name and no trailing tokens.","Delete the `head-ref` line entirely if it is optional and the head is detached — the parser treats it as absent.","Regenerate the state file by restarting the operation."],"exampleFix":"// before (state file)\nhead-ref \"refs/heads/main\" extra-token\n// after\nhead-ref \"refs/heads/main\"","handlingStrategy":"validation","validationCode":"fn head_ref_line_is_clean(line: &str) -> bool {\n    line.strip_prefix(\"head-ref \")\n        .map(|v| v.split_whitespace().count() == 1)\n        .unwrap_or(true)\n}","typeGuard":null,"tryCatchPattern":"match todo::parse(state_text) {\n    Ok(state) => apply(state),\n    Err(e) if e.to_string().contains(\"HEAD ref has trailing data\") => {\n        eprintln!(\"fix the head-ref line: one C-quoted fully-qualified ref only\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["C-quote ref names containing spaces or special bytes when writing state.","Never append extra tokens to head-ref lines when editing.","Diff state files against the tool-generated format before saving."],"tags":["rebase","state-parsing","ref-format","git"],"backgroundTag":"invalid-argument-format","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}