gitbutlerapp/gitbutler · error

Could not restore all review targets after the push failed:

Error message

Could not restore all review targets after the push failed:
{}

What it means

When a stack push fails, GitButler rewinds local branch refs back to the reviewed targets they had before the push. If any of those restore updates also fail, the accumulated per-branch errors are reported together; dissolved native GitHub stack memberships are additionally noted as not restored (the next successful push recreates them).

Source

Thrown at crates/but-api/src/legacy/forge.rs:1547

            Some(review.target_branch.clone()),
        )
        .await
        {
            errors.push(format!(
                "Failed to restore review #{} to `{}`: {err}",
                review.number, review.target_branch
            ));
        }
    }
    if !errors.is_empty() {
        if !flattening.dissolved_stacks.is_empty() {
            errors.push(
                "Native GitHub stack membership was not restored; the next successful push will \
                 recreate it."
                    .to_string(),
            );
        }
        anyhow::bail!(
            "Could not restore all review targets after the push failed:\n{}",
            errors.join("\n")
        )
    }
    if flattening.dissolved_stacks.is_empty() {
        return Ok(());
    }

    let (storage, forge_repo_info, preferred_forge_user) = {
        let ctx = ctx.into_thread_local();
        let project_meta = ctx.project_meta()?;
        let repo = ctx.repo.get()?;
        let (forge_repo_info, _) = base_and_push_repo_info(&project_meta, &repo)?;
        (
            but_forge_storage::Controller::from_path(but_path::app_data_dir()?),
            forge_repo_info,
            ctx.legacy_project.preferred_forge_user.clone(),
        )

View on GitHub (pinned to 2497b8007a)

Solutions

  1. Read the per-branch list in the message and reset those branches to their reviewed targets via the stacks UI or oplog undo
  2. Stop competing git processes on the project, then retry the push — a successful push also recreates dissolved GitHub stack memberships
  3. Run git fsck if objects are missing; restore from a healthy clone if needed
  4. If branches refuse to reset, use undo to return the workspace to a consistent snapshot
Defensive patterns

Strategy: try-catch

Validate before calling

// After any failed push, verify branches with reviews are back on their reviewed tips
for branch in branches_with_reviews {
    let reviewed = reviewed_target_oid(branch)?;
    ensure_local_ref_matches(ctx, branch, reviewed)?; // surface drift to the user early
}

Try / catch

match push_stack_with_reviews(ctx, stack).await {
    Err(err) if err.to_string().contains("Could not restore all review targets") => {
        // parse the branch list from the message, show a repair dialog,
        // offer undo or stacks-UI reset to reviewed targets
    }
    other => other,
}

Prevention

When it happens

Trigger: A push (or local target ref update) failed, and during rollback some branches could not be reset to their reviewed commits — refs locked by another process, missing objects, or concurrent ref updates.

Common situations: Another git process (IDE, hook, second GitButler instance) holds refs while the push fails; the remote changed concurrently; partially missing object store after disk issues.

Related errors


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