{"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":1881,"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":1863,"sourceCodeEnd":1899,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-api/src/legacy/forge.rs#L1863-L1899","documentation":"After a push fails, the code attempts to restore review targets (e.g. GitHub native stack membership) that were dissolved during a flattening operation. If any restoration step failed, all collected error messages are joined and thrown as one aggregate error, since review targets could not be fully recovered.","triggerScenarios":"A push triggered as part of creating a review fails, and subsequent restoration of dissolved stacks / native GitHub stack membership also reports errors.","commonSituations":"Network failure or permission error during push; GitHub API errors while restoring PR/stack membership; repo in a partially-migrated state after a failed review creation.","solutions":["Read the aggregated error body to see which specific restorations failed","Fix the underlying push failure (auth, network, remote permissions) and push successfully — native membership will be recreated on the next successful push","Recreate the dissolved stacks manually if needed, then retry review creation"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"await ensureRemoteReachable(remoteUrl); // verify auth/network before review-creating push","typeGuard":null,"tryCatchPattern":"try {\n  await createReview(projectId, opts);\n} catch (e) {\n  if (String(e).startsWith('Could not restore all review targets')) {\n    logAggregateErrors(e.message.split('\\n'));\n    // next successful push recreates native membership\n    await retryPush(projectId);\n  } else throw e;\n}","preventionTips":["Verify remote credentials and network before creating reviews","Read the aggregated error lines to identify which restorations failed","Remember next successful push recreates GitHub-native stack membership"],"tags":["rust","forge","push","github"],"backgroundTag":"api-error-response","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}