{"record":{"id":"480fa3d3c3ba66a6","repo":"gitbutlerapp/gitbutler","slug":"could-not-restore-all-review-targets-after-the-pus","errorCode":null,"errorMessage":"Could not restore all review targets after the push failed:\n{}","messagePattern":"Could not restore all review targets after the push failed:\n(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-api/src/legacy/forge.rs","lineNumber":1547,"sourceCode":"            Some(review.target_branch.clone()),\n        )\n        .await\n        {\n            errors.push(format!(\n                \"Failed to restore review #{} to `{}`: {err}\",\n                review.number, review.target_branch\n            ));\n        }\n    }\n    if !errors.is_empty() {\n        if !flattening.dissolved_stacks.is_empty() {\n            errors.push(\n                \"Native GitHub stack membership was not restored; the next successful push will \\\n                 recreate it.\"\n                    .to_string(),\n            );\n        }\n        anyhow::bail!(\n            \"Could not restore all review targets after the push failed:\\n{}\",\n            errors.join(\"\\n\")\n        )\n    }\n    if flattening.dissolved_stacks.is_empty() {\n        return Ok(());\n    }\n\n    let (storage, forge_repo_info, preferred_forge_user) = {\n        let ctx = ctx.into_thread_local();\n        let project_meta = ctx.project_meta()?;\n        let repo = ctx.repo.get()?;\n        let (forge_repo_info, _) = base_and_push_repo_info(&project_meta, &repo)?;\n        (\n            but_forge_storage::Controller::from_path(but_path::app_data_dir()?),\n            forge_repo_info,\n            ctx.legacy_project.preferred_forge_user.clone(),\n        )","sourceCodeStart":1529,"sourceCodeEnd":1565,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/2497b8007aa4a1922dae9a805b32ffe5b5037785/crates/but-api/src/legacy/forge.rs#L1529-L1565","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the per-branch list in the message and reset those branches to their reviewed targets via the stacks UI or oplog undo","Stop competing git processes on the project, then retry the push — a successful push also recreates dissolved GitHub stack memberships","Run git fsck if objects are missing; restore from a healthy clone if needed","If branches refuse to reset, use undo to return the workspace to a consistent snapshot"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// After any failed push, verify branches with reviews are back on their reviewed tips\nfor branch in branches_with_reviews {\n    let reviewed = reviewed_target_oid(branch)?;\n    ensure_local_ref_matches(ctx, branch, reviewed)?; // surface drift to the user early\n}","typeGuard":null,"tryCatchPattern":"match push_stack_with_reviews(ctx, stack).await {\n    Err(err) if err.to_string().contains(\"Could not restore all review targets\") => {\n        // parse the branch list from the message, show a repair dialog,\n        // offer undo or stacks-UI reset to reviewed targets\n    }\n    other => other,\n}","preventionTips":["Run one GitButler instance per project","Retry failed pushes promptly so local and remote states re-converge","After any failed push, check the stacks view for branches stuck between reviewed targets"],"tags":["forge","push","review","rollback","git-refs"],"backgroundTag":"rollback-failed","analyzedSha":"2497b8007aa4a1922dae9a805b32ffe5b5037785","analyzedAt":"2026-08-17T00:30:25.648Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}