GitoxideLabs/gitoxide · error
pattern still present
Error message
pattern still present
What it means
`Match::to_outer` resolves a stored pattern index against the Outcome's arena with `out.patterns.resolve(self.pattern).expect("pattern still present")`. Match results hold indices into the Outcome's pattern arena, so resolution can only fail if the Outcome (or the arenas backing it) was dropped/moved while matches referencing it outlive or bypass it — a lifetime/interning invariant.
Solutions
- Keep match results used only within the scope of the Outcome that produced them
- Never store/resolve match indices across different collection instances
- Upgrade gix to get lifetime-bound APIs if you were working around them unsafely
- Report with a minimal repro if hit through safe public APIs
Example fix
// before
let matches = { let outcome = do_search(); outcome.matches() }; // outcome dropped
resolve(matches)
// after
let outcome = do_search();
let matches = outcome.matches(); // use while outcome is alive
resolve(matches) Defensive patterns
Strategy: type-guard
Type guard
fn matches_alive<'a>(m: &[gix_attributes::search::Match<'a>], _out: &'a Outcome) -> bool { true } // rely on the borrow checker instead of unsafe Try / catch
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| match.to_outer(&outcome)));
Prevention
- Consume matches within the Outcome's scope
- Never transmute or store matches beyond their lifetime
- Avoid unsafe code around gix-attributes internals
When it happens
Trigger: Using match results after the underlying search Outcome that owns the pattern storage is no longer intact, or mixing Match values from different Outcome instances; typically prevented by the borrow-bound API, so violations indicate unsafe code or version skew.
Common situations: Storing `crate::search::Match` beyond the Outcome's lifetime via unsafe transmutes, or custom code that re-resolves indices against a rebuilt collection.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- assignment present
- only value and unspecified are possible here
- parent-match assures this
- upper match already assured we only deal with blobs
- fixed size array with three items
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/d1e6afcc0aecef32.
Report an issue: GitHub.
Appendix: source
Thrown at gix-attributes/src/search/outcome.rs:377
}
/// A version of `Match` without references.
#[derive(Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
pub struct Match {
/// The glob pattern itself, like `/target/*`.
pub pattern: RefMapKey,
/// The key=value pair of the attribute that matched at the pattern. There can be multiple matches per pattern.
pub assignment: RefMapKey,
/// Additional information about the kind of match.
pub kind: MatchKind,
/// Information about the location of the match.
pub location: MatchLocation,
}
impl Match {
fn to_outer<'a>(&self, out: &'a Outcome) -> crate::search::Match<'a> {
crate::search::Match {
pattern: out.patterns.resolve(self.pattern).expect("pattern still present"),
assignment: out
.assignments
.resolve(self.assignment)
.expect("assignment present")
.as_ref(),
kind: self.kind,
location: self.location.to_outer(out),
}
}
}
/// A version of `MatchLocation` without references.
#[derive(Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
pub struct MatchLocation {
/// The path to the source from which the pattern was loaded, or `None` if it was specified by other means.
pub source: Option<RefMapKey>,
/// The line at which the pattern was found in its `source` file, or the occurrence in which it was provided.
pub sequence_number: usize,View on GitHub (pinned to e73179060b)