quarkusio/quarkus · error · java.lang.IllegalArgumentException
PURL type contains invalid character '
Error message
PURL type contains invalid character '
What it means
validateType() rejects any character after the first one that is not an ASCII letter, digit, '.', '+' or '-'. This keeps PURL types compliant with the spec's type grammar. The offending character is reported in the message along with the full type.
Source
Thrown at independent-projects/bootstrap/app-model/src/main/java/io/quarkus/sbom/Purl.java:601
for (char c = '0'; c <= '9'; c++) {
UNRESERVED[c] = true;
}
UNRESERVED['-'] = true;
UNRESERVED['.'] = true;
UNRESERVED['_'] = true;
UNRESERVED['~'] = true;
}
private static void validateType(String type) {
char first = type.charAt(0);
if (!((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z'))) {
throw new IllegalArgumentException("PURL type must start with a letter: " + type);
}
for (int i = 1; i < type.length(); i++) {
char c = type.charAt(i);
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9') || c == '.' || c == '+' || c == '-')) {
throw new IllegalArgumentException("PURL type contains invalid character '" + c + "': " + type);
}
}
}
private static boolean isUnreserved(int c) {
return c >= 0 && c < 128 && UNRESERVED[c];
}
public static class Builder {
private String type;
private String namespace;
private String name;
private String version;
private TreeMap<String, String> qualifiers;
private String subpath;
private Builder() {View on GitHub (pinned to e1c734241f)
Solutions
- Replace invalid characters in the type: use '-', '.', or '+' where allowed, e.g. 'my-type' not 'my_type'
- Normalize the ecosystem name to the canonical PURL type (lowercase, letters/digits/./+/- only) before constructing
- Make sure only the segment between 'pkg:' and the first '/' is passed as the type, not a longer path
Example fix
// before
Purl p = Purl.parse("pkg:my_type/app@1.0");
// after
Purl p = Purl.parse("pkg:my-type/app@1.0"); Defensive patterns
Strategy: validation
Validate before calling
static boolean isValidPurlType(String type) {
if (type == null || type.isEmpty()) return false;
return type.matches("[a-zA-Z][a-zA-Z0-9.+-]*");
} Type guard
String normalizeType(String raw) {
return raw == null ? null : raw.replaceAll("[^a-zA-Z0-9.+-]", "-");
} Try / catch
try {
return Purl.parse(purlString);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("PURL type contains invalid character")) {
log.errorf("Illegal character in PURL type: %s", purlString);
}
throw e;
} Prevention
- Sanitize custom ecosystem names to [a-zA-Z0-9.+-] before use
- Never pass paths or URLs as the type component — extract only the segment after 'pkg:' and before the first '/'
- Add a unit test asserting every ecosystem constant you use passes the type regex
When it happens
Trigger: Constructing or parsing a Purl whose type contains characters like '_', '/', ' ', ':', or non-ASCII letters after the first character, e.g. 'pkg:my_type/app' or 'pkg:foo bar/baz'.
Common situations: Using underscore-separated ecosystem names ('go_module' instead of 'gomodule'); passing a whole path or URL fragment instead of just the type; embedding spaces from split coordinates or log output.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Invalid PURL:
- Invalid PURL qualifier
- type must not be empty
- name must not be empty
- Maven PURL is missing a namespace (groupId) for name (artifa
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/f2fd31c191b6198b.
Report an issue: GitHub.