jdx/mise · error
static credential globs
Error message
static credential globs
What it means
glob_set builds a GlobSet from patterns that were already filtered with Glob::new(... if let Ok), so builder.build() is expected to be infallible and is unwrapped with expect("static credential globs"). A panic means GlobSetBuilder rejected a glob that Glob::new accepted, an upstream-inconsistency scenario.
Solutions
- Update the glob/globset crates to compatible versions
- Verify the credential glob patterns compile with Glob::new in isolation if debugging
- Replace expect with a graceful error if patterns ever become user-validated rather than compile-time static
Defensive patterns
Strategy: fallback
Validate before calling
// verify patterns compile before use
for p in patterns {
Glob::new(p).expect("invalid credential glob pattern");
} Try / catch
let globset = builder.build()
.map_err(|e| anyhow!("failed to build credential globs: {e}"))?; Prevention
- Keep glob and globset crate versions in sync
- Unit-test credential glob construction with representative patterns
- Prefer returning errors over expect even for 'infallible' builds
When it happens
Trigger: Practically unreachable for users; fires only if GlobSetBuilder::build fails on globs already validated by Glob::new, e.g. after a glob crate version change alters build() validation.
Common situations: Maintainers touching the credential glob builder after a glob/globset dependency update.
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
- each version token has one matching kind
- affected project exists in graph
- an operation record always has an operation
- attestation requests must not have a streaming body
- bootstrap command is registered
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/e07fdf1ce14354da.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/history/tracked.rs:638
/// Credential stores mise itself knows by name; they mean something only
/// under the global configuration directory.
fn credential_names() -> GlobSet {
glob_set(CREDENTIAL_NAMES)
}
/// Key material by name pattern, private wherever it is captured.
fn credential_globs() -> GlobSet {
glob_set(CREDENTIAL_GLOBS)
}
fn glob_set(patterns: &[&str]) -> GlobSet {
let mut builder = GlobSetBuilder::new();
for pattern in patterns {
if let Ok(glob) = Glob::new(pattern) {
builder.add(glob);
}
}
builder.build().expect("static credential globs")
}
/// The `[history] exclude` globs, applied in order with the last match
/// deciding: a `!glob` after a broader glob re-includes what it matches.
#[derive(Debug, Default)]
pub(crate) struct ExcludeSet {
patterns: Vec<(globset::GlobMatcher, bool)>,
}
impl ExcludeSet {
pub(crate) fn new(globs: &[String]) -> Result<Self> {
let mut patterns = vec![];
for glob in globs {
let (pattern, negated) = match glob.strip_prefix('!') {
Some(rest) => (rest, true),
None => (glob.as_str(), false),
};
let expanded = file::replace_path(Path::new(pattern));View on GitHub (pinned to 533346cc37)