gitbutlerapp/gitbutler · error
too many IDs
Error message
too many IDs
What it means
GitButler assigns short `UintId` identifiers (committed-file markers etc.) from a monotonically increasing counter capped at `UintId::LIMIT`. `next_available` first advances the counter past any marked-in-use IDs and then bails if the counter reached the limit, meaning the operation can no longer allocate a unique ID.
Solutions
- Reduce the number of entries in the workspace (commit/clean up applied files) and retry.
- Reset the workspace state so the ID counter restarts (e.g. by re-initializing the session).
- If hit with a normal number of files, file a bug — IDs are likely being leaked rather than reused.
Defensive patterns
Strategy: try-catch
Validate before calling
// guard before allocating more IDs
if usage.next_available().is_err() { /* reduce workspace entries or reset */ }
Try / catch
match id_usage.next_available() {
Err(e) if e.to_string() == "too many IDs" => cleanup_workspace_and_retry(),
other => other?,
} Prevention
- Commit or remove workspace entries regularly so IDs don't accumulate unbounded.
- Monitor workspace size; keep applied-file counts well below the ID limit.
- Report leaks if the error occurs with few files.
When it happens
Trigger: Repeatedly calling next_available (e.g. assigning IDs to many workspace files/committed entries) until next_uint_id reaches UintId::LIMIT within a single workspace/session state.
Common situations: Workspaces with an extreme number of tracked/committed entries in one session; long-lived state where IDs are never released; a bug leaking ID allocations.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- a committed transaction always materializes a workspace
- Ad-hoc (single-branch) branch moves are not supported…
- assignments_error: assignments_error.map(|err|…
- Branch ' ' cannot be created: the target commit ( ) already…
- Branch ` ` is not part of the current workspace
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/b9462ce74819342c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but/src/id/id_usage.rs:104
#[derive(Clone, Default, Debug)]
pub(crate) struct IdUsage {
/// A [UintId] is used if it's in this set.
uint_ids_used: HashSet<UintId>,
/// A [UintId] is used if it's less than this number.
next_uint_id: UintId,
}
impl IdUsage {
pub(crate) fn mark_used(&mut self, uint_id: UintId) {
if self.next_uint_id.0 <= uint_id.0 {
self.uint_ids_used.insert(uint_id);
}
}
pub(crate) fn next_available(&mut self) -> anyhow::Result<UintId> {
self.forward_next_uint_id_to_not_conflict_with_marked();
if self.next_uint_id.0 >= UintId::LIMIT {
bail!("too many IDs");
}
let result = self.next_uint_id;
self.next_uint_id = UintId(self.next_uint_id.0 + 1);
Ok(result)
}
pub(crate) fn skip_available(&mut self) {
self.forward_next_uint_id_to_not_conflict_with_marked();
if self.next_uint_id.0 < UintId::LIMIT {
self.next_uint_id = UintId(self.next_uint_id.0 + 1);
}
}
pub(crate) fn forward_next_uint_id_to_not_conflict_with_marked(&mut self) {
while self.uint_ids_used.remove(&self.next_uint_id) {
self.next_uint_id = UintId(self.next_uint_id.0 + 1);
}
}View on GitHub (pinned to 58e5313667)