GitoxideLabs/gitoxide · error
a fork section contains no commits
Error message
a fork section contains no commits
What it means
When parsing an edited rebase todo, lines are processed bottom-up and each `──fork <id>──` separator starts a new fork section. Before opening a new section, the previous one must contain at least one line (a command or reference line). An empty fork section is rejected because it would produce no plan steps.
Solutions
- Remove the leftover `──fork ...──` separator for the now-empty section
- Add back at least one command or reference line under the fork heading
- Reopen the todo editor and let tix regenerate the template before editing
Example fix
// before ──fork abc1234── ──fork def5678── pick 1111111 // after ──fork abc1234── pick abc1234 ──fork def5678── pick 1111111
Defensive patterns
Strategy: validation
Validate before calling
// check each fork section has content before saving the todo
let sections: Vec<&str> = text.split("──fork ").skip(1).collect();
for s in §ions {
let body = s.splitn(2, '\n').nth(1).unwrap_or("");
if body.trim().is_empty() {
return Err("fork section has no commands or references");
}
} Try / catch
if let Err(e) = parse(repo, edited) {
if e.to_string().contains("fork section contains no commits") {
// reopen the editor or strip the empty fork heading automatically
}
} Prevention
- Delete the fork separator when emptying a section
- Preview the todo diff before saving
- Regenerate the template instead of editing from memory
When it happens
Trigger: `parse` bails when it encounters a fork separator while `sections > 0 && !section_has_commit` — i.e. a previous fork section contained only another fork heading (or nothing) with no commit-producing lines between them. Happens when a user deletes all lines within a fork section in the editor but leaves the heading.
Common situations: Manually cleaning up the todo file and deleting the contents of a fork section but not its fork separator; editor macros stripping lines; pasting malformed todo templates.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- a fork target must be picked before it is used
- a reference is placed more than once
- the rebase todo cannot select a checkout without a worktree
- the rebase todo contains more than one @ reference
- the rebase todo contains more than one @ command
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/c386ea5fe44fd01c.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/todo.rs:874
if line.starts_with("<!--") {
in_comment = !line.contains("-->");
continue;
}
if line.is_empty() || line.starts_with("# ") {
continue;
}
editable.push(line);
}
for line in editable.into_iter().rev() {
if line.starts_with('─') && line.ends_with('─') {
let target = line
.trim_matches('─')
.trim()
.strip_prefix("fork ")
.context("a fork separator needs a fork ID")?;
if sections > 0 && !section_has_commit {
anyhow::bail!("a fork section contains no commits");
}
let id = resolve_commit(
repo,
target
.split_whitespace()
.next()
.context("a fork heading needs a commit ID")?,
)?;
cursor = Some(if let Some(index) = picked.get(&id) {
rebase::PlanParent::Step(*index)
} else if scope.contains(&id) {
anyhow::bail!("a fork target must be picked before it is used");
} else {
rebase::PlanParent::Existing(id)
});
sections += 1;
section_has_commit = false;
section_last_step = None;View on GitHub (pinned to e73179060b)