GitoxideLabs/gitoxide · error
the rebase todo cannot select a checkout without a worktree
Error message
the rebase todo cannot select a checkout without a worktree
What it means
A reference line can mark a ref with `@` to select it as the checkout target after the rebase. This is only possible when the rebase state records checkout as allowed and the repository has a worktree; a bare repository or a checkout-disallowed state cannot honor the selection, so the todo is rejected.
Solutions
- Remove the `@` marker from the reference line
- Run the rebase in a non-bare repository with a worktree attached
- Restart the rebase in a mode that permits checkout before using `@` selection
Example fix
// before (main @) // after (bare repo / checkout disallowed) (main)
Defensive patterns
Strategy: validation
Validate before calling
if edited.contains("@)") || edited.contains(" @\n") {
if !checkout_allowed || repo.workdir().is_none() {
return Err("cannot use @ checkout selection without a worktree");
}
} Type guard
fn can_use_checkout_marker(repo: &gix::Repository, checkout_allowed: bool) -> bool {
checkout_allowed && repo.workdir().is_some()
} Try / catch
if let Err(e) = parse(repo, edited) {
if e.to_string().contains("without a worktree") {
// strip @ markers or open a non-bare worktree
}
} Prevention
- Check `repo.workdir().is_some()` before offering checkout selection in UIs
- Strip `@` markers when serializing todos for bare repositories
- Document that checkout selection requires a worktree
When it happens
Trigger: `parse` bails when a `@`-marked reference in a `( ... )` line is parsed while `state.checkout_allowed` is false or `repo.workdir()` is None. Happens when editing todos in a bare clone or when the rebase state was started in a mode that disallows checkout.
Common situations: Running tix in a bare repository or CI checkout without a worktree; carrying a `@` marker over from a template used in a normal clone; state started with checkout disabled.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- cannot delete because another worktree has it checked out
- a detached checked-out root commit cannot be removed
- a fork section contains no commits
- a fork target must be picked before it is used
- a reference is placed more than once
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/f3b7779da355a8ad.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/edit/todo.rs:904
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;
continue;
}
if line.starts_with('(') && line.ends_with(')') {
let target = cursor.context("a reference line must follow a fork or command")?;
for (marked, value) in parse_ref_line(line)? {
let name = resolve_ref_name(repo, &mut state.expected_refs, value.as_bstr())?;
if ref_targets.insert(name.clone(), target).is_some() {
anyhow::bail!("a reference is placed more than once");
}
if marked {
if !state.checkout_allowed || repo.workdir().is_none() {
anyhow::bail!("the rebase todo cannot select a checkout without a worktree");
}
if explicit_checkout_reference.replace((name, target)).is_some() {
anyhow::bail!("the rebase todo contains more than one @ reference");
}
}
}
section_has_commit = true;
continue;
}
let (command, tail) = if let Some(line) = line.strip_prefix('`') {
let (command, tail) = line
.split_once('`')
.context("a Markdown todo command has no closing backtick")?;
(command, tail.trim())
} else {
(line, "")
};View on GitHub (pinned to e73179060b)