{"record":{"id":"1a2dc60e14e96bab","repo":"quarkusio/quarkus","slug":"invalid-purl","errorCode":null,"errorMessage":"Invalid PURL: ","messagePattern":"Invalid PURL: ","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"independent-projects/bootstrap/app-model/src/main/java/io/quarkus/sbom/Purl.java","lineNumber":118,"sourceCode":"        return new Purl(type, namespace, name, version, Collections.emptyMap(), null);\n    }\n\n    public static Builder builder() {\n        return new Builder();\n    }\n\n    /**\n     * Parses a canonical PURL string.\n     *\n     * @param purlString a PURL string starting with \"pkg:\"\n     * @return the parsed Purl\n     * @throws IllegalArgumentException if the string is not a valid PURL\n     */\n    public static Purl parse(String purlString) {\n        Objects.requireNonNull(purlString, \"purlString is null\");\n        Matcher m = PURL_PATTERN.matcher(purlString);\n        if (!m.matches()) {\n            throw new IllegalArgumentException(\"Invalid PURL: \" + purlString);\n        }\n\n        String type = m.group(1);\n        String namespaceName = m.group(2);\n        String versionRaw = m.group(3);\n        String qualifiersRaw = m.group(4);\n        String subpathRaw = m.group(5);\n\n        String namespace = null;\n        String name;\n        int lastSlashIdx = namespaceName.lastIndexOf('/');\n        if (lastSlashIdx < 0) {\n            name = percentDecode(namespaceName);\n        } else {\n            name = percentDecode(namespaceName.substring(lastSlashIdx + 1));\n            namespace = decodePath(namespaceName.substring(0, lastSlashIdx));\n        }\n","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/sbom/Purl.java#L100-L136","documentation":"Purl.parse() validates a package URL (purl) string against the PURL_PATTERN regex and throws IllegalArgumentException 'Invalid PURL: <str>' when it does not match the purl spec structure pkg:<type>/<namespace>/<name>@<version>?<qualifiers>#<subpath>.","triggerScenarios":"Calling Purl.parse(purlString) with a string lacking the 'pkg:' scheme, empty type/name, illegal characters, or otherwise not conforming to the purl grammar.","commonSituations":"SBOM tooling receiving hand-written or third-party purl strings; migrated SBOM data from other tools with non-canonical purls; typos like 'pkg:maven/quarkus' (missing coordinates).","solutions":["Fix the purl string to the canonical form: pkg:type/namespace/name@version?qualifiers#subpath (e.g. pkg:maven/io.quarkus/quarkus-core@3.0.0)","Validate the string with the purl spec grammar before parsing","If it came from another tool, regenerate the SBOM/purl with a spec-compliant generator"],"exampleFix":"// before\nPurl.parse(\"maven:io.quarkus:quarkus-core:3.0.0\");\n// after\nPurl.parse(\"pkg:maven/io.quarkus/quarkus-core@3.0.0\");","handlingStrategy":"validation","validationCode":"if (s == null || !s.startsWith(\"pkg:\")) { throw new IllegalArgumentException(\"Not a purl: \" + s); }\nPurl.parse(s);","typeGuard":"boolean looksLikePurl(String s) { return s != null && s.startsWith(\"pkg:\") && java.util.regex.Pattern.matches(\"^pkg:[a-zA-Z0-9._-]+/[^/]+/[^/@?#]+(@[^?#]*)?(\\\\?.*)?(#.*)?$\", s); }","tryCatchPattern":"try { Purl.parse(purlString); } catch (IllegalArgumentException e) { log.warn(\"Skipping invalid purl: \" + purlString); }","preventionTips":["Use spec-compliant purl generators only","Unit-test purl strings produced by your tooling","Sanitize purls imported from third-party SBOMs"],"tags":["sbom","purl","validation"],"backgroundTag":"invalid-package-url","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}