{"record":{"id":"960ff4ecf7baa003","repo":"gitbutlerapp/gitbutler","slug":"no-uncommitted-changes-to-discard","errorCode":null,"errorMessage":"No uncommitted changes to discard","messagePattern":"No uncommitted changes to discard","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/but/src/command/legacy/discard.rs","lineNumber":458,"sourceCode":"                match selection {\n                    UncommittedSelection::All => builder.push_changes_from_uncommitted_area()?,\n                    UncommittedSelection::Changes(changes) => {\n                        for change in *changes {\n                            match change {\n                                UncommittedDiscardSource::HunkOrFile(change) => {\n                                    builder.push_changes_from_uncommitted(&change)?;\n                                }\n                                UncommittedDiscardSource::PathPrefix(hunks) => {\n                                    builder.push_changes_from_path_prefix(&hunks)?;\n                                }\n                            }\n                        }\n                    }\n                }\n                builder.reconcile_worktree_diff_specs()?;\n                builder.into_diff_specs()\n            };\n            anyhow::ensure!(!changes.is_empty(), \"No uncommitted changes to discard\");\n            let paths = paths_from_changes(&changes);\n            ExecutableDiscardOperation::Uncommitted { paths, changes }\n        }\n    };\n\n    let (mut outcome, mut ws) = but_transaction::with_transaction_with_perm(\n        ctx,\n        meta,\n        perm,\n        SnapshotDetails::new(oplog_operation_kind),\n        DryRun::No,\n        |mut tx| {\n            let outcome = match executable {\n                ExecutableDiscardOperation::Branches { branches, commits } => {\n                    if !commits.is_empty() {\n                        tx.discard_commits(commits.iter().map(|c| c.commit_id))?;\n                    }\n                    for branch in &branches {","sourceCodeStart":440,"sourceCodeEnd":476,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but/src/command/legacy/discard.rs#L440-L476","documentation":"For uncommitted discards, DiffSpecBuilder accumulates specs from the selected uncommitted changes (hunks/files/path-prefixes), reconciles them against the worktree, then ensure! requires at least one resulting spec. The error means the selection resolved to zero actual worktree changes — e.g. the selected hunks were already discarded, files reverted externally, or the selectors matched nothing dirty. Discard then refuses to open a transaction and record an oplog entry for a no-op.","triggerScenarios":"Calling discard-uncommitted with selectors from a stale ID map after another tool (editor autosave-revert, git checkout --) already cleared the changes; or with filters whose reconcile_worktree_diff_specs() produced an empty set.","commonSituations":"Two windows both operating on the worktree; retrying a discard that already succeeded; IDE auto-reverting a file between `but id` and the discard call.","solutions":["Check the worktree is still dirty for those paths: `git status` / `git diff` — if clean, there is nothing to discard.","Refresh selectors with `but id` and re-run if changes still exist under different IDs.","Avoid concurrent revert operations while issuing discards."],"exampleFix":"# before\n$ but discard 2b   # hunk 2b was already discarded\nError: No uncommitted changes to discard\n\n# after\n$ but id   # pick a currently dirty change\n$ but discard 5f","handlingStrategy":"validation","validationCode":"// Confirm the worktree is still dirty before discarding\nif repo.status_dirty_paths().is_empty() {\n    return Ok(()); // nothing uncommitted, nothing to discard\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = discard_uncommitted(ctx, selection) {\n    if e.to_string().contains(\"No uncommitted changes to discard\") {\n        return Ok(()); // benign: selection already clean\n    }\n    return Err(e);\n}","preventionTips":["Avoid concurrent editors/reverts while running discard commands.","Refresh selectors via `but id` immediately before use."],"tags":["discard","worktree","diff","guard"],"backgroundTag":"nothing-to-discard","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}