{"record":{"id":"ae53bd1cf73559cb","repo":"gitbutlerapp/gitbutler","slug":"failed-to-find-reference-ref-name-due-to-it-bein","errorCode":null,"errorMessage":"Failed to find reference {ref_name} due to it being dropped in the traversal overlay","messagePattern":"Failed to find reference (.+?) due to it being dropped in the traversal overlay","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but-graph/src/init/overlay.rs","lineNumber":200,"sourceCode":"        if self.dropped_references.contains(ref_name) {\n            Ok(None)\n        } else if let Some(r) = self.overriding_references.get(ref_name) {\n            Ok(Some(r.clone().attach(self.inner)))\n        } else if let Some(rn) = self.inner.try_find_reference(ref_name)? {\n            Ok(Some(rn))\n        } else if let Some(r) = self.nonoverriding_references.get(ref_name) {\n            Ok(Some(r.clone().attach(self.inner)))\n        } else {\n            Ok(None)\n        }\n    }\n\n    pub fn find_reference(\n        &self,\n        ref_name: &gix::refs::FullNameRef,\n    ) -> anyhow::Result<gix::Reference<'repo>> {\n        if self.dropped_references.contains(ref_name) {\n            bail!(\n                \"Failed to find reference {ref_name} due to it being dropped in the traversal overlay\"\n            );\n        }\n        if let Some(r) = self.overriding_references.get(ref_name) {\n            return Ok(r.clone().attach(self.inner));\n        }\n        Ok(self\n            .inner\n            .find_reference(ref_name)\n            .or_else(|err| match err {\n                gix::reference::find::existing::Error::Find(_) => Err(err),\n                gix::reference::find::existing::Error::NotFound { .. } => {\n                    if let Some(r) = self.nonoverriding_references.get(ref_name) {\n                        Ok(r.clone().attach(self.inner))\n                    } else {\n                        Err(err)\n                    }\n                }","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-graph/src/init/overlay.rs#L182-L218","documentation":"Thrown by TraversalOverlay::find_reference (crates/but-graph/src/init/overlay.rs:200) when asked for a ref that the overlay has explicitly dropped. The traversal overlay hides refs (e.g., refs consumed by the workspace/virtual branches) so the graph sees a curated refdb; lookups of dropped refs deliberately fail fast instead of returning None or leaking the underlying repo's ref — silently succeeding would break the overlay's invariants. Overriding refs are served from the overlay map, non-overriding ones from nonoverriding_references, and only then does it fall through to the inner repository.","triggerScenarios":"Calling overlay.find_reference() for a branch whose commits are absorbed into the GitButler workspace (its ref was dropped from the overlay); looking up a ref that init decided to hide during traversal setup; code that mixes overlay lookups with raw-repo assumptions querying a hidden ref.","commonSituations":"Workspace code that assumes all repo refs remain visible under the overlay; tests constructing an overlay with dropped refs and then querying them; tooling that enumerates refs before init and resolves them after init dropped some.","solutions":["Do not resolve refs you know the workspace manages — check membership in the dropped set (or your own record of dropped refs) before lookup","Use the Option-returning lookup path (the one consulting nonoverriding_references and returning Ok(None)) when 'dropped' and 'missing' should both mean absent","If you genuinely need the physical ref, query the inner repository directly, understanding it bypasses overlay semantics"],"exampleFix":"// before\nlet reference = overlay.find_reference(&ref_name)?; // bails for workspace-dropped refs\n\n// after: treat 'dropped by overlay' as not-found\nlet reference = match overlay.find_reference(&ref_name) {\n    Ok(r) => Some(r),\n    Err(err) if err.to_string().contains(\"dropped in the traversal overlay\") => None,\n    Err(err) => return Err(err),\n};","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"let reference = match overlay.find_reference(&ref_name) {\n    Ok(r) => Some(r),\n    Err(err) if err.to_string().contains(\"dropped in the traversal overlay\") => {\n        None // dropped and missing both mean 'not present' in the overlay view\n    }\n    Err(err) => return Err(err),\n};","preventionTips":["Never look up refs you know init dropped — track the dropped set alongside the overlay","For physical-ref questions, query the inner repository explicitly instead of the overlay"],"tags":["but-graph","overlay","git-refs","traversal","rust"],"backgroundTag":"overlay-dropped-reference","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}