{"record":{"id":"02d979e3ad9071d2","repo":"gitbutlerapp/gitbutler","slug":"reference-step-must-have-a-non-empty-virtual-branc","errorCode":null,"errorMessage":"Reference step must have a non-empty virtual branch name","messagePattern":"Reference step must have a non-empty virtual branch name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-rebase/src/lib.rs","lineNumber":196,"sourceCode":"        match step {\n            RebaseStep::Pick { commit_id, .. } => {\n                self.assure_unique_step_and_existing_non_base(commit_id, \"Picked\")?;\n            }\n            RebaseStep::SquashIntoPreceding {\n                commit_id,\n                new_message: _,\n            } => {\n                self.assure_unique_step_and_existing_non_base(commit_id, \"Fixup\")?;\n                if matches!(self.steps.last(), Some(RebaseStep::Reference { .. })) {\n                    bail!(\"Fixup commit must not come after a reference step\");\n                }\n                if self.steps.is_empty() {\n                    bail!(\"Fixup must have a commit to work on\");\n                }\n            }\n            RebaseStep::Reference(name) => {\n                if matches!(name, but_core::Reference::Virtual(name) if name.is_empty()) {\n                    return Err(anyhow!(\n                        \"Reference step must have a non-empty virtual branch name\"\n                    ));\n                }\n            }\n        }\n        Ok(())\n    }\n\n    fn assure_unique_step_and_existing_non_base(\n        &self,\n        commit_id: &gix::oid,\n        kind: &str,\n    ) -> Result<()> {\n        self.repo.find_commit(commit_id)?;\n        if Some(commit_id) == self.base.as_deref() {\n            bail!(\"{kind} commit cannot be the base commit\");\n        }\n        if self.steps.iter().any(|s| s.commit_id() == Some(commit_id)) {","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-rebase/src/lib.rs#L178-L214","documentation":"`Rebase::steps()` validates each step as it is added; a `RebaseStep::Reference(but_core::Reference::Virtual(name))` with an empty `name` is rejected because a virtual-branch reference needs a branch name to point at. Reference steps create/update refs after the rebase, so an empty virtual name would produce an unusable reference. Non-virtual references (e.g. regular git refs) are not affected by this check.","triggerScenarios":"Pushing `RebaseStep::Reference(Reference::Virtual(String::new()))` or building the step from an unset workspace/virtual branch name field; defaults from `Default::default()`-style construction where the name was never filled in.","commonSituations":"Serialization round-trips that lose the branch name; UI flows that create a reference step for a workspace branch whose name failed to generate; test fixtures built with placeholder empty strings.","solutions":["Set a real virtual branch name, e.g. `Reference::Virtual(\"gitbutler/workspace\".into())`","Trace where the step was constructed and assert the name is non-empty at that boundary","Skip emitting the Reference step entirely when there is no name — usually the step itself is optional"],"exampleFix":"// before\nrebase.steps([RebaseStep::Reference(but_core::Reference::Virtual(String::new()))])?; // Err\n\n// after\nrebase.steps([RebaseStep::Reference(but_core::Reference::Virtual(\n    \"gitbutler/workspace\".into(),\n))])?;","handlingStrategy":"validation","validationCode":"if let RebaseStep::Reference(but_core::Reference::Virtual(name)) = &step {\n    anyhow::ensure!(!name.is_empty(), \"virtual branch name must not be empty\");\n}\nrebase.steps([step])?;","typeGuard":"fn has_non_empty_virtual_name(step: &RebaseStep) -> bool {\n    !matches!(step, RebaseStep::Reference(but_core::Reference::Virtual(name)) if name.is_empty())\n}","tryCatchPattern":null,"preventionTips":["Construct Reference steps only from names obtained from the workspace branch API","Assert non-empty names at the boundary where steps are built","Skip emitting the Reference step when no name exists instead of defaulting one"],"tags":["rust","rebase","validation","virtual-branches","references"],"backgroundTag":"empty-string-argument","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}