{"record":{"id":"c472f14f590d9575","repo":"gitbutlerapp/gitbutler","slug":"failed-to-determine-push-remote-for-dry-run-push","errorCode":null,"errorMessage":"Failed to determine push remote for dry-run push: workspace target has no push remote.","messagePattern":"Failed to determine push remote for dry-run push: workspace target has no push remote\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but/src/command/legacy/push.rs","lineNumber":228,"sourceCode":"                t.hint.paint(\"No branches have unpushed commits.\")\n            )?;\n        }\n        return Ok(());\n    }\n\n    // Get detailed information for each branch\n    let mut dry_run_infos = Vec::new();\n\n    let stacks = crate::legacy::workspace::applied_stacks_with_expensive_commit_info(ctx)?;\n\n    // Limit the shared lock to target resolution before continuing with dry-run analysis.\n    let fallback_remote = {\n        let guard = ctx.shared_worktree_access();\n        workspace_target::ResolvedTarget::resolve_with_perm(ctx, guard.read_permission())?\n            .push_remote_name()\n            .map(str::to_owned)\n            .ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"Failed to determine push remote for dry-run push: workspace target has no push remote.\"\n                )\n            })?\n    };\n    let repo = ctx.repo.get()?.clone().for_commit_shortening();\n    let remote_names = repo.remote_names();\n    for (branch_name, unpushed_count, stack_name) in &branches_to_show {\n        // Find the stack containing this branch\n        for stack_entry in &stacks {\n            if stack_entry.id.is_some()\n                && let Some(branch_detail) = stack_entry.branch(branch_name)\n            {\n                let remote_ref = match repo\n                    .branch_remote_tracking_ref_name(\n                        branch_detail.reference.as_ref(),\n                        gix::remote::Direction::Fetch,\n                    )\n                    .transpose()?","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but/src/command/legacy/push.rs#L210-L246","documentation":"`but push --dry-run` resolves the workspace target under a shared lock and needs its push remote to describe what a real push would update. `ResolvedTarget::resolve_with_perm(...)?.push_remote_name()` returning `None` aborts the dry run with this error before any branch analysis happens.","triggerScenarios":"Running `but push --dry-run` when the workspace target carries no push remote: target branch never fully configured, push remote not derivable from the target ref, or the remote missing from the repo.","commonSituations":"Target set without an explicit push remote on an unusual remote layout; remote renamed (origin to upstream) after onboarding; fresh clone with partially applied workspace config.","solutions":["Set target together with a push remote: `but config target <branch> <push-remote>` (e.g. `but config target origin/main origin`)","Or set the push remote alone: `but config push-remote <remote>`","Check `git remote -v` and run `git fetch` so the target ref exists on that remote","Re-run `but push --dry-run`"],"exampleFix":"# before\nbut push --dry-run\n# error: Failed to determine push remote for dry-run push: workspace target has no push remote.\n\n# after\nbut config push-remote origin\nbut push --dry-run","handlingStrategy":"validation","validationCode":"# Ensure target + push remote before any dry-run in scripts\nbut config target origin/main origin\ngit remote -v | grep -q '^origin' || { echo 'missing remote: origin' >&2; exit 1; }\nbut push --dry-run","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Configure target branch and push remote as one setup step","Re-check configuration after renaming remotes","Treat dry-run failures as config signals — they precede any real push and change nothing"],"tags":["push","dry-run","push-remote","workspace-target"],"backgroundTag":"no-push-remote-configured","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}