gitbutlerapp/gitbutler · error

implement list and call recursively

Error message

implement list and call recursively

What it means

In crates/but/src/lib.rs dispatch_subcommand, the `but branch` command with no subcommand panics via todo!("implement list and call recursively") when the binary is built without the "legacy" feature. With the legacy feature, it delegates to command::legacy::branch::handle_no_subcommand instead.

Solutions

  1. Use `but branch list` explicitly, which avoids the no-subcommand arm.
  2. Build/install the CLI with the legacy feature enabled (cargo build --features legacy) to get the historical bare-branch behavior.
  3. Implement the non-legacy path in crates/but/src/lib.rs: list branches and recurse into the branch subcommand dispatch.

Example fix

// before
but branch
// after
but branch list
Defensive patterns

Strategy: validation

Validate before calling

# shell guard before invoking
if but branch --help 2>/dev/null | grep -q list; then
  but branch list
else
  echo "bare 'but branch' unsupported on this build"
fi

Prevention

When it happens

Trigger: Running `but branch` (no subcommand) on a non-legacy build — the cfg arm selects the todo!() and the CLI panics.

Common situations: Installing `but` from a build without the legacy feature and trying the bare `but branch` listing command; CI scripts relying on the legacy shorthand against a modern build.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/a6f0f529451ca8b7. Report an issue: GitHub.

Appendix: source

Thrown at crates/but/src/lib.rs:1014

                }
                worktree::Subcommands::Unarchive { worktree } => {
                    let outcome = command::worktree::archive::set_archived(&ctx, &worktree, false)?;
                    out.print_cli_output(outcome)?;
                }
                worktree::Subcommands::Remove { force, worktree } => {
                    let outcome = command::worktree::remove::remove(&mut ctx, &worktree, force)?;
                    out.print_cli_output(outcome)?;
                }
                worktree::Subcommands::New { name } => {
                    let outcome = command::worktree::new::new(&mut ctx, name.as_ref())?;
                    out.print_cli_output(outcome)?;
                }
            }
            None
        }
        Subcommands::Branch(branch::Platform { cmd }) => match cmd {
            #[cfg(not(feature = "legacy"))]
            None => todo!("implement list and call recursively"),
            #[cfg(feature = "legacy")]
            None => {
                command::legacy::branch::handle_no_subcommand(&mut ctx, out)?;
                None
            }
            #[cfg(feature = "legacy")]
            Some(branch::Subcommands::List {
                filter,
                local,
                remote,
                all,
                no_ahead,
                review,
                no_check,
                empty,
            }) => {
                command::legacy::branch::list_branches(
                    &mut ctx, out, filter, local, remote, all, no_ahead, review, no_check, empty,

View on GitHub (pinned to 58e5313667)