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

  1. Remove the leftover `──fork ...──` separator for the now-empty section
  2. Add back at least one command or reference line under the fork heading
  3. 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 &sections {
    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

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


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)