jdx/mise · error

unopened brace alternate in glob pattern {pattern:?}

Error message

unopened brace alternate in glob pattern {pattern:?}

What it means

When expanding brace alternates (`{a,b}`) in task glob patterns, find_group scans for `{`/`}`. A `}` encountered while group_depth == 0 means there is no matching opening brace, so the pattern is malformed and the function bails. This protects glob expansion from silently treating an unbalanced pattern as a literal.

Source

Thrown at src/task/task_source_checker.rs:101

                continue;
            }
            match ch {
                '[' if class_depth == 0 => class_depth = 1,
                ']' if class_depth == 1 => class_depth = 0,
                '{' if class_depth == 0 => {
                    if group_depth == 0 {
                        group_start = Some(idx);
                        branch_start = idx + ch.len_utf8();
                    }
                    group_depth += 1;
                }
                ',' if class_depth == 0 && group_depth == 1 => {
                    branches.push((branch_start, idx));
                    branch_start = idx + ch.len_utf8();
                }
                '}' if class_depth == 0 => {
                    if group_depth == 0 {
                        bail!("unopened brace alternate in glob pattern {pattern:?}");
                    }
                    group_depth -= 1;
                    if group_depth == 0 {
                        let start = group_start.unwrap();
                        if !branches.is_empty() {
                            branches.push((branch_start, idx));
                            return Ok(Some(BraceGroup {
                                start,
                                end: idx,
                                branches,
                            }));
                        }

                        // A balanced group without a top-level comma is a
                        // literal brace pair. It may still contain a nested
                        // alternate, so look inside it before continuing with
                        // the remainder of the pattern.
                        if let Some(mut nested) = find_group(&pattern[start + 1..idx])? {

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Add the missing opening `{` or remove the stray `}` in the glob pattern
  2. Escape a literal brace as `\{`/`\}` if it should match literally
  3. Validate the pattern by running the task after editing mise.toml

Example fix

// before (mise.toml)
sources = ['src/*.ts}']
// after
sources = ['src/{a,b}/*.ts']
Defensive patterns

Strategy: validation

Validate before calling

// js: quick brace-balance check for task globs before writing config
function bracesBalanced(p) {
  let d = 0;
  for (const ch of p.replace(/\\./g, '')) {
    if (ch === '{') d++;
    if (ch === '}') { if (--d < 0) return false; }
  }
  return d === 0;
}
bracesBalanced('src/{a,b}/*.ts'); // true

Prevention

When it happens

Trigger: Passing a task source/output glob containing `}` without a preceding `{` to expand_glob_braces, e.g. via task file patterns like `dist/*.js}` or an escaped brace typo.

Common situations: Hand-edited task globs in mise.toml where an opening `{` was deleted or mis-escaped; copy-paste from docs that dropped the `{`; glob classes `[}]` mistaken for brace syntax.

Related errors


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