gitbutlerapp/gitbutler · critical

Database file at '{db_path} has {max_attempts} corrupted cop

Error message

Database file at '{db_path} has {max_attempts} corrupted copies - giving up, application probably won't work

What it means

Thrown when the startup db-quarantine loop finds every numbered backup name taken. Each failed open renames the db to <db_name>.maybe-broken-NN for NN in 1..255; if all slots already exist, the app gives up because the database keeps getting corrupted and no more quarantine copies fit. Like its projects.json twin (controller.rs), it signals repeated corruption with no cleanup.

Source

Thrown at crates/gitbutler-tauri/src/projects.rs:156

            if backup_path.is_file() {
                continue;
            }

            if let Err(err) = std::fs::rename(&db_path, &backup_path) {
                bail!(
                    "Failed to rename {} to {} - application may fail to startup: {err}",
                    db_path.display(),
                    backup_path.display()
                );
            }

            return Ok(Some(format!(
                "Could not open db file at '{}'.\nIt was moved to {} for recovery. \n\nError was: {err}",
                db_path.display(),
                backup_path.display()
            )));
        }
        bail!(
            "Database file at '{db_path} has {max_attempts} corrupted copies - giving up, application probably won't work",
            db_path = db_path.display()
        );
    }
    Ok(None)
}

/// Return an error message that
fn warn_about_filters_and_git_lfs(repo: &gix::Repository) -> anyhow::Result<Option<String>> {
    let index = repo.index_or_empty()?;
    let mut cache = repo.attributes_only(
        &index,
        gix::worktree::stack::state::attributes::Source::WorktreeThenIdMapping,
    )?;
    let mut attrs = cache.selected_attribute_matches(Some("filter"));
    let mut all_filters = BTreeSet::<String>::new();
    let mut files_with_filter = Vec::new();
    for entry in index.entries() {

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Close the app and delete or archive the accumulated <db_name>.maybe-broken-* files, then relaunch so quarantine can run again
  2. Check the newest quarantine copy with sqlite3 <file> 'PRAGMA integrity_check;' to confirm real corruption versus an environment problem
  3. Fix the root cause: one app instance, no cloud-sync on the data dir, current app version, healthy disk
  4. If the data matters, recover what you need from the newest good copy before letting the app start fresh

Example fix

# before: 254 quarantine copies, startup gives up
ls "$DATA_DIR"/*.maybe-broken-* | wc -l
# after: archive them, keep the newest for inspection, relaunch
mkdir -p ~/gb-db-backups
mv "$DATA_DIR"/*.maybe-broken-* ~/gb-db-backups/
sqlite3 ~/gb-db-backups/$(ls -1 ~/gb-db-backups | tail -1) 'PRAGMA integrity_check;'
Defensive patterns

Strategy: validation

Validate before calling

let quarantined: Vec<_> = std::fs::read_dir(data_dir)?
    .filter_map(|e| e.ok())
    .filter(|e| e.file_name().to_string_lossy().contains(".maybe-broken-"))
    .collect();
if quarantined.len() > 50 {
    // archive them now, before startup recovery exhausts its 255 slots
}

Prevention

When it happens

Trigger: The project db open fails AND files <db_name>.maybe-broken-01 through -254 already exist in the data dir, so the 'for round in 1..max_attempts' loop never finds a free name and falls through to the bail.

Common situations: A persistent corruption source (failing disk, sync tool, two app versions fighting over the schema) corrupting the db on every launch; users relaunching repeatedly with each launch adding one quarantine copy; data dirs migrated wholesale including all old quarantine files.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/2678a2279c1fdbf7. Report an issue: GitHub.