apple/pkl · error · InvalidUserDataException
Failed to parse Pkl module file path
Error message
Failed to parse Pkl module file path: ${s} What it means
parseModuleNotation accepts a String notation for a Pkl module. If the string is not a valid URI it falls back to interpreting it as a filesystem path; when Paths.get(s) throws InvalidPathException or UnsupportedOperationException, the library wraps it in this InvalidUserDataException so Gradle reports which notation string could not be parsed.
Solutions
- Fix the notation string so it is either a valid module URI (e.g. pkl:, https:, file:) or a valid filesystem path for the OS
- Use a java.io.File or FileSystemLocation (project.layout.files/projectDir.resolve(...)) notation instead of a raw String
- Check the string for illegal characters (NUL bytes, invalid separators) before passing it
- Print/log the offending notation (it is included in the message) and correct it in build scripts or task inputs
Example fix
// before
pklModules = listOf("pkl:base?\u0000")
// after
pklModules = listOf("pkl:base") Defensive patterns
Strategy: validation
Validate before calling
// Java/Gradle
static boolean isValidNotation(String s) {
try { java.nio.file.Paths.get(s); return true; }
catch (java.nio.file.InvalidPathException | UnsupportedOperationException e) { return false; }
}
// call before assigning: if (!isValidNotation(notation)) throw new IllegalArgumentException(...); Type guard
static boolean isSafeModuleNotation(Object n) {
return n instanceof String s && isValidNotation(s) || n instanceof java.io.File || n instanceof org.gradle.api.file.FileSystemLocation;
} Try / catch
try {
file = PluginUtils.parseModuleNotation(notation);
} catch (InvalidUserDataException e) {
logger.error("Bad Pkl module notation: {}", e.getMessage());
throw new GradleException("Fix module notation: " + notation, e);
} Prevention
- Validate notation strings (no NUL/illegal path chars) before passing to Pkl tasks
- Prefer File or FileSystemLocation notations over raw strings
- Keep URIs and paths distinct in build configuration; don't paste URIs into path fields
When it happens
Trigger: Passing a String to a Pkl Gradle plugin module property (e.g. pkl project/module configuration) that contains characters illegal in a filesystem path, such as a NUL byte, or a URI-formatted string on a platform whose Path implementation rejects it (UnsupportedOperationException from Paths.get).
Common situations: Typos or unescaped characters in pklModulePath/pklModule URIs, copy-pasting a URI into a field expected to be a path, Windows path handling with unusual characters, or generating notation strings programmatically with embedded nulls.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Could not find a source set for code generator
- Invalid test reporter
- No source modules specified.
- Unsupported value of type
- cannotFindCertFile
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/b49bf707c584a5ce.
Report an issue: GitHub.
Appendix: source
Thrown at pkl-gradle/src/main/java/org/pkl/gradle/utils/PluginUtils.java:103
} else if (notation instanceof URL url) {
try {
return parseModuleNotation(url.toURI());
} catch (URISyntaxException e) {
throw new InvalidUserDataException("Failed to parse Pkl module URI: " + notation, e);
}
} else if (notation instanceof CharSequence) {
var s = notation.toString();
if (IoUtils.isUriLike(s)) {
try {
return parseModuleNotation(IoUtils.toUri(s));
} catch (URISyntaxException e) {
throw new InvalidUserDataException("Failed to parse Pkl module URI: " + s, e);
}
} else {
try {
return Paths.get(s).toFile();
} catch (InvalidPathException | UnsupportedOperationException e) {
throw new InvalidUserDataException("Failed to parse Pkl module file path: " + s, e);
}
}
} else if (notation instanceof FileSystemLocation location) {
return location.getAsFile();
} else {
throw new InvalidUserDataException(
"Unsupported value of type "
+ notation.getClass()
+ " used as a module path: "
+ notation);
}
}
/**
* Converts either a file or a URI to a URI. We convert a relative file to a URI via the {@link
* IoUtils#createUri(String)} because other ways of conversion can make relative paths into
* absolute URIs, which may break module loading.
*/View on GitHub (pinned to f3efcbfc9b)