{"record":{"id":"81feb1642e5e1a8a","repo":"quarkusio/quarkus","slug":"invalid-purl-qualifier","errorCode":null,"errorMessage":"Invalid PURL qualifier ","messagePattern":"Invalid PURL qualifier ","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":151,"sourceCode":"            name = percentDecode(namespaceName.substring(lastSlashIdx + 1));\n            namespace = decodePath(namespaceName.substring(0, lastSlashIdx));\n        }\n\n        String version = versionRaw != null && !versionRaw.isEmpty() ? percentDecode(versionRaw) : null;\n\n        Map<String, String> qualifiers = Map.of();\n        if (qualifiersRaw != null) {\n            TreeMap<String, String> parsed = null;\n            String singleKey = null;\n            String singleValue = null;\n            int pairStart = 0;\n            int len = qualifiersRaw.length();\n            while (pairStart <= len) {\n                int ampIdx = qualifiersRaw.indexOf('&', pairStart);\n                int pairEnd = ampIdx < 0 ? len : ampIdx;\n                int eqIdx = qualifiersRaw.indexOf('=', pairStart);\n                if (eqIdx < 0 || eqIdx > pairEnd) {\n                    throw new IllegalArgumentException(\n                            \"Invalid PURL qualifier '\" + qualifiersRaw.substring(pairStart, pairEnd)\n                                    + \"': missing '=' in \" + purlString);\n                }\n                if (eqIdx == pairStart) {\n                    throw new IllegalArgumentException(\n                            \"Invalid PURL qualifier '\" + qualifiersRaw.substring(pairStart, pairEnd)\n                                    + \"': empty key in \" + purlString);\n                }\n                String key = qualifiersRaw.substring(pairStart, eqIdx).toLowerCase();\n                String value = percentDecode(qualifiersRaw.substring(eqIdx + 1, pairEnd));\n                if (parsed != null) {\n                    parsed.put(key, value);\n                } else if (singleKey != null) {\n                    parsed = new TreeMap<>();\n                    parsed.put(singleKey, singleValue);\n                    parsed.put(key, value);\n                } else {\n                    singleKey = key;","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/bootstrap/app-model/src/main/java/io/quarkus/sbom/Purl.java#L133-L169","documentation":"Thrown while parsing the qualifier section of a package URL (purl) string in Purl.parse: a key=value pair inside the qualifiers segment is malformed (missing '=' or empty key), so the qualifier cannot be decoded and the whole purl is rejected as invalid.","triggerScenarios":"Purl.parse() on a purl whose qualifier section has a key without '=', e.g. pkg:maven/g/a@1.0?packaging or ?a&b=1.","commonSituations":"Hand-assembled purl strings in CI scripts; SBOM data imported from non-conformant tools; typos in generated qualifiers.","solutions":["Add the missing '=' and value for the qualifier: ?key=value","Remove qualifiers that have no value","Validate the qualifier string matches key=value pairs joined by '&' before parsing"],"exampleFix":"// before\nPurl.parse(\"pkg:maven/g/a@1.0?packaging\");\n// after\nPurl.parse(\"pkg:maven/g/a@1.0?packaging=jar\");","handlingStrategy":"validation","validationCode":"for (String pair : qualifierPart.split(\"&\")) { if (!pair.contains(\"=\")) throw new IllegalArgumentException(\"Qualifier missing '=': \" + pair); }","typeGuard":"boolean validQualifiers(String q) { return java.util.Arrays.stream(q.split(\"&\")).allMatch(p -> p.indexOf('=') > 0); }","tryCatchPattern":"try { Purl.parse(purl); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"missing '='\")) { fixQualifier(purl); } else { throw e; } }","preventionTips":["Always emit qualifiers as key=value pairs","Validate purls at the boundary where they enter your system","Avoid hand-building purls in scripts"],"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"}