gitbutlerapp/gitbutler · error

{}

Error message

{}

What it means

This is the catch-all error for `CliId::AnonymousSegment`: the given id resolved to an anonymous (unnamed) commit segment, and diff specs cannot be computed for it. The actual message text is produced by `anonymous_segment_error(&segment.id)`, which explains that the anonymous segment cannot be targeted.

Solutions

  1. Use the id of a named commit, hunk, or file instead of the anonymous segment id
  2. Assign the anonymous changes to a commit/branch first, then reference that id
  3. Re-run `but status` to identify the nearest concrete commit id
Defensive patterns

Strategy: validation

Validate before calling

if let CliId::AnonymousSegment(seg) = &id {
    eprintln!("{} is an anonymous segment; pick a named commit/hunk/file id", seg.id);
    return Ok(());
}

Type guard

fn is_anonymous_segment(id: &CliId) -> bool { matches!(id, CliId::AnonymousSegment(_)) }

Try / catch

if let Err(e) = cmd() { if e.to_string().contains("anonymous") || is_segment_error(&e) { /* re-pick a concrete id */ } else { return Err(e); } }

Prevention

When it happens

Trigger: Calling an operation whose diff-spec building path hits `push_changes_from_id` with a `CliId::AnonymousSegment` id, e.g. passing an anonymous-segment id from `but status` to a diff-specs-backed command.

Common situations: Selecting the unnamed area between labeled commits in `but status`/TUI output and passing that id to a command; scripting with ids copied from a visualization that includes anonymous segments.

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


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

Appendix: source

Thrown at crates/but/src/utils/diff_specs.rs:75

            CliId::PathPrefix {
                id: _,
                hunks,
                source: _,
            } => self.push_changes_from_path_prefix(hunks),
            CliId::CommittedFile {
                committed_file:
                    CommittedFileId {
                        commit_id,
                        path,
                        change_id: _,
                    },
                id: _,
            } => self.push_changes_from_committed_file(*commit_id, path.as_ref()),
            CliId::Branch(branch) => {
                anyhow::bail!("Cannot compute diff specs for branch `{}`", branch.name)
            }
            CliId::AnonymousSegment(segment) => {
                anyhow::bail!("{}", anonymous_segment_error(&segment.id))
            }
            CliId::Commit {
                commit:
                    CommitId {
                        commit_id,
                        change_id: _,
                    },
                id: _,
            } => self.push_changes_from_commit(*commit_id),
            CliId::Uncommitted { id: _ } => self.push_changes_from_uncommitted_area(),
            // A worktree's uncommitted area is expanded into its files during
            // resolution, so the builder only ever sees hunks that already come from
            // its own repo. The reference holds no changes at all.
            CliId::Worktree { name, .. } | CliId::WorktreeUncommitted { name, .. } => {
                anyhow::bail!("Cannot compute diff specs for worktree `{name}`")
            }
            CliId::Stack { .. } => {
                anyhow::bail!("Cannot compute diff specs for stacks")

View on GitHub (pinned to 58e5313667)