jdx/mise · error

source pattern did not match {path}

Error message

source pattern did not match {path}

What it means

Wildcards in a dotfile source pattern (`*`, `?`, `[...]`) are compiled to a regex and matched against the discovered path to capture directory segments used to build the expanded target. If a candidate path does not match the pattern at all, `wildcard_captures` cannot derive target components and errors instead of producing a malformed expansion.

Source

Thrown at src/system/files.rs:1169

                policy,
                variants: vec![],
                enabled,
            })
        })
        .collect()
}

fn is_glob_pattern(path: &Path) -> bool {
    path.to_string_lossy()
        .chars()
        .any(|c| matches!(c, '*' | '?' | '['))
}

fn wildcard_captures(pattern: &str, path: &Path) -> Result<Vec<String>> {
    let path = normalize_path_separators(&path.to_string_lossy());
    let re = wildcard_regex(pattern)?;
    let Some(captures) = re.captures(&path) else {
        bail!("source pattern did not match {path}");
    };
    Ok((1..captures.len())
        .map(|i| {
            captures
                .get(i)
                .map(|m| m.as_str().to_string())
                .unwrap_or_default()
        })
        .collect())
}

fn wildcard_regex(pattern: &str) -> Result<Regex> {
    let mut re = String::from("^");
    let pattern = normalize_path_separators(pattern);
    let mut chars = pattern.chars().peekable();
    while let Some(ch) = chars.next() {
        match ch {
            '*' if chars.peek() == Some(&'*') => {

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Check the pattern in the message against the actual path printed; adjust the wildcards (add `**/` for arbitrary depth, `?` for single chars) so the path matches.
  2. Ensure the source file actually lives under the dotfiles root at the location the pattern describes.
  3. Re-run dotfiles apply/status so discovery re-runs against the current tree (clears stale paths).
  4. If you wrote a custom regex-like pattern, verify its syntax matches the tool's wildcard dialect (`wildcard_regex`).

Example fix

// before: pattern configs/*.conf cannot match nested file
source = "configs/*.conf"  # found configs/editors/vim.conf

// after
source = "configs/**/*.conf"
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check a pattern against sample paths using the same wildcard dialect
function patternMatches(pattern, path) {
  const re = new RegExp('^' + pattern.replace(/\*\*/g, '.*').replace(/\*/g, '[^/]*').replace(/\?/g, '.') + '$');
  return re.test(path);
}

Try / catch

try {
  expandWildcards();
} catch (e) {
  if (/source pattern did not match/.test(e.message)) {
    const path = e.message.split('did not match ')[1];
    console.error(`Adjust the wildcard pattern so it matches ${path} (check depth and separators)`);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the wildcard expansion path (e.g. via `expand_request`) with a path whose normalized form is not matched by the source pattern's regex — typically a path from a different depth or directory shape than the pattern expects.

Common situations: Changing a source pattern (e.g. from `configs/*.conf` to `configs/**/*.conf`) so previously matching files no longer match; symlinks or `..` segments altering the normalized path; running expansion on a stale cached path after the dotfiles root moved.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/d3a3637b1f185292. Report an issue: GitHub.