openai/codex · error · anyhow::Error

glob pattern must not be empty

Error message

glob pattern must not be empty

What it means

Matcher strings prefixed with 'pattern:' are compiled as globset globs; 'pattern:' with nothing after the colon is an empty glob, which parse_matcher_pattern rejects with 'glob pattern must not be empty'. The rule applies wherever matchers are accepted: path_prefixes, query allowed-values, and header allowed-values.

Source

Thrown at codex-rs/network-proxy/src/mitm_hook.rs:517

        .map(|value| match parse_matcher_pattern(value)? {
            MatcherPattern::Literal(value) => Ok(ValueMatcher::Exact(value.to_string())),
            MatcherPattern::Glob(glob_pattern) => Ok(ValueMatcher::Glob(compile_glob_matcher(
                glob_pattern,
                /*literal_separator*/ false,
            )?)),
        })
        .collect()
}

fn parse_matcher_pattern(pattern: &str) -> Result<MatcherPattern<'_>> {
    if let Some(literal) = pattern.strip_prefix(LITERAL_PREFIX) {
        return Ok(MatcherPattern::Literal(literal));
    }
    let Some(glob_pattern) = pattern.strip_prefix(PATTERN_PREFIX) else {
        return Ok(MatcherPattern::Literal(pattern));
    };
    if glob_pattern.is_empty() {
        return Err(anyhow!("glob pattern must not be empty"));
    }
    Ok(MatcherPattern::Glob(glob_pattern))
}

fn compile_glob_matcher(pattern: &str, literal_separator: bool) -> Result<CompiledGlobMatcher> {
    let mut builder = GlobBuilder::new(pattern);
    builder
        .backslash_escape(true)
        .literal_separator(literal_separator);
    builder
        .build()
        .map(|glob| CompiledGlobMatcher {
            pattern: pattern.to_string(),
            matcher: glob.compile_matcher(),
        })
        .map_err(|err| anyhow!("invalid glob pattern {pattern:?}: {err}"))
}

View on GitHub (pinned to 339751715c)

Solutions

  1. Put the glob after the colon, e.g. "pattern:/api/*/items"
  2. Drop the 'pattern:' prefix entirely to treat the string as a literal
  3. For 'match all paths' use "/" as a plain prefix entry instead of an empty glob

Example fix

# before
path_prefixes = ["pattern:"]

# after
path_prefixes = ["pattern:/api/*/items"]
Defensive patterns

Strategy: validation

Validate before calling

// Rust — no bare pattern: prefix
let values: Vec<&String> = config.mitm_hooks.iter()
    .flat_map(|h| h.matcher.path_prefixes.iter()
        .chain(h.matcher.query.values().flatten())
        .chain(h.matcher.headers.values().flatten()))
    .collect();
if values.iter().any(|v| v.as_str() == "pattern:") {
    return Err(anyhow!("empty glob after pattern: prefix"));
}

Type guard

fn matcher_is_well_formed(v: &str) -> bool {
    v != "pattern:"
}

Try / catch

match validate_mitm_hook_config(&config) {
    Ok(()) => {}
    Err(err) => eprintln!("{err:#}"), // points at the field holding the empty glob
}

Prevention

When it happens

Trigger: path_prefixes = ["pattern:"], or a query/header allowed-values list containing the exact string "pattern:" — any matcher equal to the bare prefix, from compile_path_matchers or compile_value_matchers.

Common situations: Template substitution meant to fill the glob body but rendered empty; deleting the pattern body while refactoring; expecting the bare prefix to mean 'match everything'.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/ecd9cf4b1287e95f. Report an issue: GitHub.