apple/pkl · error · IllegalArgumentException
Rewrite rule must end with '/', but was
Error message
Rewrite rule must end with '/', but was '%s'
What it means
validateRewriteRule also requires rewrite rule URIs to end with '/' so that rule keys and targets behave as directory-like prefixes. This IllegalArgumentException is thrown when the rule URI is http(s) but lacks the trailing slash.
Solutions
- Append a trailing '/' to the rewrite rule URI in your configuration
- Normalize the URI string before passing it to the API (add '/' if missing)
- Re-run with the corrected value in PklProject.yml or CLI flags
Example fix
// before
rewrite { ["example.com/pkg/"] = "https://mirror.example/pkg" }
// after
rewrite { ["example.com/pkg/"] = "https://mirror.example/pkg/" } Defensive patterns
Strategy: validation
Validate before calling
if (!ruleStr.endsWith("/")) ruleStr = ruleStr + "/"; Type guard
function endsWithSlash(u) { return u.toString().endsWith("/"); } Try / catch
try { IoUtils.validateRewriteRule(rewrite) } catch (IllegalArgumentException e) { /* auto-append slash or report config error */ } Prevention
- Normalize rule URIs by appending '/' before validation
- Store rewrite targets with trailing slashes in config templates
- Add a config lint that enforces trailing slashes on prefix-style URIs
When it happens
Trigger: validateRewriteRule receives e.g. https://localhost:8080/mypackage (no trailing slash) as a rewrite rule from --rewrite-settings or project config.
Common situations: Writing rewrite targets in config without the trailing slash, causing prefix matching to fail or be ambiguous.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Rewrite rule must start with 'http://' or 'https://', but…
- invalidUri
- Cannot generate documentation for just one module within a…
- Cannot resolve relative URI
- cannotAnalyzeRelativeModuleUri
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/bf38a474e3e690ed.
Report an issue: GitHub.
Appendix: source
Thrown at pkl-core/src/main/java/org/pkl/core/util/IoUtils.java:905
}
return index;
}
public static void validateFileUri(URI uri) throws URISyntaxException {
if (!uri.getSchemeSpecificPart().startsWith("/")) {
throw new URISyntaxException(uri.toString(), ErrorMessages.create("invalidOpaqueFileUri"));
}
}
public static void validateRewriteRule(URI rewrite) {
if (!Objects.equals(rewrite.getScheme(), "http")
&& !Objects.equals(rewrite.getScheme(), "https")) {
throw new IllegalArgumentException(
"Rewrite rule must start with 'http://' or 'https://', but was '%s'".formatted(rewrite));
}
if (!rewrite.toString().endsWith("/")) {
throw new IllegalArgumentException(
"Rewrite rule must end with '/', but was '%s'".formatted(rewrite));
}
}
private static boolean isReservedHeaderName(String headerName) {
var normalizedHeader = headerName.toLowerCase(Locale.ROOT);
for (var reservedHeader : reservedHeaderNames) {
if (normalizedHeader.equals(reservedHeader)) {
return true;
}
}
return false;
}
private static boolean hasReservedHeaderPrefix(String headerName) {
var normalizedHeader = headerName.toLowerCase(Locale.ROOT);
for (var prefix : reservedHeaderPrefixes) {
if (normalizedHeader.startsWith(prefix)) {View on GitHub (pinned to f3efcbfc9b)