GitoxideLabs/gitoxide · error
the rebase state has more than one onto target
Error message
the rebase state has more than one onto target
What it means
Like `base`, the `onto` key in the rebase state anchor is single-valued. A second `onto <oid>` line makes the rebase's target commit ambiguous, so `parse_state` refuses the state instead of silently choosing one.
Solutions
- Delete the extra `onto` line, keeping the correct target oid.
- Regenerate the state anchor via tix rather than editing it manually.
- Abort the rebase and restart to obtain a clean state block.
- Sanity-check the anchor: `grep -c '^onto '` must return 1.
Example fix
// before (inside anchor body) // onto aaa111... // onto bbb222... let state = parse_state(repo, text)?; // bails // after // onto aaa111... (single, correct onto) let state = parse_state(repo, &dedupe_state_lines(text))?;
Defensive patterns
Strategy: validation
Validate before calling
let onto_lines = body.lines().filter(|l| l.starts_with("onto ")).count();
if onto_lines > 1 {
anyhow::bail!("state anchor declares onto more than once");
} Try / catch
match parse(repo, todo_text) {
Ok(s) => s,
Err(e) if e.to_string().contains("more than one onto target") => {
// fix the anchor to a single onto line, then retry
}
Err(e) => return Err(e),
} Prevention
- Avoid hand-editing state anchors; regenerate via tix
- Check duplicated lines after applying patches to todo files
- Lint anchor bodies: each of base/onto must appear exactly once
When it happens
Trigger: Calling `parse` on a todo whose state anchor body lists `onto <oid>` more than once — duplicated state lines from hand edits, bad merges, or buggy generators.
Common situations: Manual anchor editing introducing a stray onto line; a merge/patch that duplicated the onto line inside the same anchor; scripted todo generation writing onto twice.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- the rebase todo contains more than one state anchor
- the rebase state has more than one base
- the rebase todo uses an unsupported state version
- cannot find character that we didn't search for
- (re-raised revision-spec parse error via bail!(err))
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/8c50610b75e860a5.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/todo.rs:690
let mut scope = Vec::new();
let mut marker_required = None;
let mut checkout_allowed = None;
let mut head_ref = None;
let mut edit_refs = false;
let mut expected_refs = Vec::new();
let mut resolved = None;
let mut continuation_sources = Vec::new();
for line in body[..end].lines() {
let (key, value) = line.split_once(' ').context("a rebase state line has no value")?;
match key {
"base" => {
if base.replace(ObjectId::from_hex(value.as_bytes())?).is_some() {
anyhow::bail!("the rebase state has more than one base");
}
}
"onto" => {
if onto.replace(ObjectId::from_hex(value.as_bytes())?).is_some() {
anyhow::bail!("the rebase state has more than one onto target");
}
}
"tip" => tips.push(ObjectId::from_hex(value.as_bytes())?),
"scope" => scope.push(ObjectId::from_hex(value.as_bytes())?),
"marker-required" => {
if marker_required.replace(value.parse()?).is_some() {
anyhow::bail!("the rebase state repeats marker-required");
}
}
"checkout-allowed" => {
if checkout_allowed.replace(value.parse()?).is_some() {
anyhow::bail!("the rebase state repeats checkout-allowed");
}
}
"head-ref" => {
let encoded = value.as_bytes().as_bstr();
let (name, consumed) = gix::quote::ansi_c::undo(encoded)
.map_err(gix::Exn::into_error)View on GitHub (pinned to e73179060b)