apple/pkl · error · InvalidGlobPatternException

invalidGlobInvalidEscapeCharacter

invalidGlobInvalidEscapeCharacter

Error message

invalidGlobInvalidEscapeCharacter

What it means

Pkl's GlobResolver translates glob patterns into Java regexes, and a backslash in a glob is an escape character that must be followed by one of ? * [ { or another backslash. If the character after the escape is anything else (e.g. \d or \s, which are regex escapes but not glob escapes), the pattern is rejected as invalid because it would silently change meaning. The error includes the offending character as a message parameter.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/util/GlobResolver.java:189

          } else {
            sb.append('}');
          }
        }
        case ',' -> {
          if (inGroup) {
            sb.append(")|(?:");
          } else {
            sb.append(',');
          }
        }
        case '\\' -> {
          var next = getNextChar(globPattern, i);
          if (next == NULL) {
            throw new InvalidGlobPatternException(
                ErrorMessages.create("invalidGlobInvalidTerminatingCharacter"));
          }
          if (next != '?' && next != '*' && next != '[' && next != '{' && next != '\\') {
            throw new InvalidGlobPatternException(
                ErrorMessages.create("invalidGlobInvalidEscapeCharacter", next));
          }
          sb.append('\\').append(next);
          i++;
        }
        case '[' -> i = consumeCharacterClass(globPattern, i, sb);
        case '?' -> {
          var next = getNextChar(globPattern, i);
          if (next == '(') {
            throw new InvalidGlobPatternException(ErrorMessages.create("invalidGlobExtGlob"));
          }
          sb.append(".");
        }
        case '*' -> {
          var next = getNextChar(globPattern, i);
          if (next == '(') {
            throw new InvalidGlobPatternException(ErrorMessages.create("invalidGlobExtGlob"));
          } else if (next == '*') {

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Remove the backslash or replace the regex-style escape with glob syntax (e.g. \d -> [0-9], \. -> .)
  2. If a literal character is meant, verify it does not need escaping in glob (only ? * [ ] { } \ are special)
  3. Double every backslash if the pattern passes through a layer that itself processes escapes (shell, properties file, JSON)

Example fix

// before
glob("logs/\d+/*.pkl")
// after
glob("logs/[0-9]+/*.pkl")
Defensive patterns

Strategy: validation

Validate before calling

function isValidGlobEscape(pattern) {
  return !/\\(?[^?*[\\{]|$)/.test(pattern); // false if a backslash precedes an unsupported char
}

Type guard

function hasValidEscapes(p) {
  for (let i = 0; i < p.length; i++) {
    if (p[i] === '\\') {
      const n = p[i+1];
      if (n !== '?' && n !== '*' && n !== '[' && n !== '{' && n !== '\\') return false;
      i++;
    }
  }
  return true;
}

Try / catch

try {
  var regex = GlobResolver.toRegexPattern(glob);
} catch (InvalidGlobPatternException e) {
  // handle invalid glob: report message, fall back to literal path
}

Prevention

When it happens

Trigger: Passing a glob pattern (e.g. to `glob(...)` imports or a glob-based resource/project resolution API such as GlobResolver.toRegexPattern/toRegexString) that contains a backslash not followed by ?, *, [, {, or \\ — most commonly regex-style escapes like \d, \w, \., or a trailing backslash would instead raise invalidGlobInvalidTerminatingCharacter.

Common situations: Developers copying a regex into a glob field (\d+ instead of [0-9]+), escaping spaces or dots out of habit, or shell-escaping a path that then carries stray backslashes into the pattern.

Related errors


AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/19185393857bceac. Report an issue: GitHub.