gitbutlerapp/gitbutler · warning

deduping a NonEmpty will never make it empty

Error message

deduping a NonEmpty will never make it empty

What it means

Near-unreachable invariant in non_empty_dedup_maintain_sort: deduplicating a NonEmpty always retains its first element, so the output Vec is never empty and from_vec always succeeds. A panic here would require a modified loop that filters out every element including the first - ordinary code changes cannot produce it, and it cannot be triggered by input.

Source

Thrown at crates/but/src/command/legacy/squash.rs:1703

        .commits
        .iter()
        .map(|commit| commit.id)
        .map(|id| CommitId::try_from_commit_id(id, repo))
        .collect::<anyhow::Result<Vec<_>>>()?;
    Ok(commits_in_segment)
}

fn non_empty_dedup_maintain_sort<T>(non_empty: NonEmpty<T>) -> NonEmpty<T>
where
    T: Ord,
{
    let mut out = Vec::new();
    for item in non_empty {
        if !out.contains(&item) {
            out.push(item);
        }
    }
    NonEmpty::from_vec(out).expect("deduping a NonEmpty will never make it empty")
}

View on GitHub (pinned to 2497b8007a)

Solutions

  1. No user action; if observed, suspect a locally modified build
  2. Maintainer: construct the result as NonEmpty { head, tail } directly and delete the expect

Example fix

// before
NonEmpty::from_vec(out).expect("deduping a NonEmpty will never make it empty")

// after - keep non-emptiness structural
let mut it = non_empty.into_iter();
let head = it.next().expect("iterator over NonEmpty yields one");
let mut tail = Vec::new();
let mut seen = vec![head.clone()];
for item in it {
    if !seen.contains(&item) {
        seen.push(item.clone());
        tail.push(item);
    }
}
NonEmpty { head, tail }
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Only a patched or future version of the loop that drops the first item (for example switching to 'retain' on the output while excluding the head); no runtime input reaches it.

Common situations: Practically none; relevant as a code-review note when touching this helper during squash-related refactors.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@2497b8007a (2026-08-17). Data as JSON: /api/errors/3ecc3161827286d9. Report an issue: GitHub.