{"record":{"id":"facb08ba2d01e0d1","repo":"gitbutlerapp/gitbutler","slug":"cannot-compute-diff-specs-for-stacks","errorCode":null,"errorMessage":"Cannot compute diff specs for stacks","messagePattern":"Cannot compute diff specs for stacks","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but/src/utils/diff_specs.rs","lineNumber":93,"sourceCode":"                anyhow::bail!(\"{}\", anonymous_segment_error(&segment.id))\n            }\n            CliId::Commit {\n                commit:\n                    CommitId {\n                        commit_id,\n                        change_id: _,\n                    },\n                id: _,\n            } => self.push_changes_from_commit(*commit_id),\n            CliId::Uncommitted { id: _ } => self.push_changes_from_uncommitted_area(),\n            // A worktree's uncommitted area is expanded into its files during\n            // resolution, so the builder only ever sees hunks that already come from\n            // its own repo. The reference holds no changes at all.\n            CliId::Worktree { name, .. } | CliId::WorktreeUncommitted { name, .. } => {\n                anyhow::bail!(\"Cannot compute diff specs for worktree `{name}`\")\n            }\n            CliId::Stack { .. } => {\n                anyhow::bail!(\"Cannot compute diff specs for stacks\")\n            }\n            CliId::CommittedHunk(_) => {\n                anyhow::bail!(\"Cannot compute diff specs for committed hunks\")\n            }\n        }\n    }\n\n    pub fn push_changes_from_uncommitted(\n        &mut self,\n        uncommitted: &UncommittedHunkOrFile,\n    ) -> anyhow::Result<()> {\n        // Specs are built against one checkout's repository, so a hunk from\n        // another would silently address the wrong files. Operations that support\n        // worktree sources validate the selection and construct the builder via\n        // [`Self::for_change_source`]; the rest read the main worktree and refuse\n        // worktree hunks here.\n        if uncommitted.source != self.source {\n            if let Some(name) = uncommitted.source.worktree_name() {","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but/src/utils/diff_specs.rs#L75-L111","documentation":"Unsupported-kind guard in the diff-spec builder's push_changes_from_id: a stack CliId was passed, but diff specs can only be computed for concrete change sources (commits, uncommitted areas, hunks), not whole stacks. The caller must expand or narrow the selection to supported ID kinds.","triggerScenarios":"Passing a `CliId::Stack` id (e.g. a stack name shown in `but status`) to a command whose id handling goes through `push_changes_from_id`.","commonSituations":"Using the stack name from `but status` output where a commit, hunk, or file id is expected; automation that iterates stacks and feeds stack ids into per-change commands.","solutions":["Pass a specific commit, hunk, or file id within the stack instead of the stack id","List the stack's commits first (e.g. `but log <stack>`) and choose a concrete id","Use a command designed for stack-level operations if a whole-stack action is intended"],"exampleFix":"// before\nbut <op> my-stack    # stack id -> error\n// after\nbut <op> abc123f     # a commit id inside the stack","handlingStrategy":"validation","validationCode":"if matches!(id, CliId::Stack{..}) {\n    eprintln!(\"stack ids cannot build diff specs; pick a commit inside the stack\");\n    return Ok(());\n}","typeGuard":"fn is_stack_id(id: &CliId) -> bool { matches!(id, CliId::Stack{..}) }","tryCatchPattern":"if let Err(e) = cmd() { if e.to_string().contains(\"for stacks\") { /* fall back to per-commit ids */ } else { return Err(e); } }","preventionTips":["Resolve stacks to their commits before issuing per-change commands","Distinguish stack ids from commit ids in `but status` output","Reject stack ids early in automation pipelines"],"tags":["cli","stack","diff"],"backgroundTag":"unsupported-operation","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"}