apple/pkl · error · InvalidGlobPatternException
invalidGlobExtGlob
invalidGlobExtGlob
Error message
invalidGlobExtGlob
What it means
GlobResolver rejects extended-glob syntax: a `?` immediately followed by `(` would begin an extglob alternation like ?(a|b), which this glob implementation does not support. A plain `?` matches exactly one character, so `?(` is rejected rather than misinterpreted.
Solutions
- Rewrite the extglob alternation as a brace or character-class expansion, e.g. "?(main|test).pkl" -> "{main,test}.pkl"
- Escape or restructure so `(` is not immediately after `?` — a literal `(` should appear as `(` alone (it is escaped by the translator) not right after a wildcard
- Use separate globs for each alternative
Example fix
// before
glob("?(a|b).pkl")
// after
glob("{a,b}.pkl") Defensive patterns
Strategy: validation
Validate before calling
/\?\(/.test(glob) // true means unsupported extglob ?( — rewrite before use
Type guard
const supportsPlainGlobOnly = (p) => !/\?\(/.test(p);
Try / catch
try {
var regex = GlobResolver.toRegexPattern(glob);
} catch (InvalidGlobPatternException e) {
if (e.getMessage().contains("extglob")) throw new IllegalArgumentException("extglob ?( syntax unsupported; use {a,b}");
throw e;
} Prevention
- Do not copy bash extglob patterns into Pkl globs
- Prefer brace expansion {a,b} over extglob alternations
- Document that only ? * ** [..] {..} \ are supported
When it happens
Trigger: Calling toRegexPattern/toRegexString (via glob import or resource glob resolution) with a pattern where `?` is directly followed by `(`, e.g. "?(main|test).pkl".
Common situations: Copying patterns from bash with extglob enabled (shopt -s extglob) or from tools like minimatch/jq that support extglob syntax into a Pkl glob.
Related errors
- cannotGlobTripleDots
- cannotGlobUri
- cannotGlobUri
- externalReaderFailure
- invalidGlobInvalidCharacterInCharacterClass
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/3526fc5096155dde.
Report an issue: GitHub.
Appendix: source
Thrown at pkl-core/src/main/java/org/pkl/core/util/GlobResolver.java:199
}
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 == '*') {
// globstar, crosses directory boundaries
sb.append(".*");
i++;
} else {
// single wildcard matches everything up until the next directory character
sb.append("[^/]*");
}
}
case '+', '@' -> {
var next = getNextChar(globPattern, i);View on GitHub (pinned to f3efcbfc9b)