{"id":"634a92886465f1aa","repo":"junit-team/junit5","slug":"s-is-not-a-well-formed-uniqueid-segment","errorCode":null,"errorMessage":"'%s' is not a well-formed UniqueId segment","messagePattern":"'(.+?)' is not a well-formed UniqueId segment","errorType":"exception","errorClass":"JUnitException","httpStatus":null,"severity":"error","filePath":"junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java","lineNumber":97,"sourceCode":"\t\tencodedCharacterMap.computeIfAbsent(segmentDelimiter, UniqueIdFormat::encode);\n\t}\n\n\t/**\n\t * Parse a {@code UniqueId} from the supplied string representation.\n\t *\n\t * @return a properly constructed {@code UniqueId}\n\t * @throws JUnitException if the string cannot be parsed\n\t */\n\tUniqueId parse(String source) throws JUnitException {\n\t\tString[] parts = source.split(String.valueOf(this.segmentDelimiter));\n\t\tList<Segment> segments = Arrays.stream(parts).map(this::createSegment).toList();\n\t\treturn new UniqueId(segments);\n\t}\n\n\tprivate Segment createSegment(String segmentString) throws JUnitException {\n\t\tMatcher segmentMatcher = this.segmentPattern.matcher(segmentString);\n\t\tif (!segmentMatcher.matches()) {\n\t\t\tthrow new JUnitException(\"'%s' is not a well-formed UniqueId segment\".formatted(segmentString));\n\t\t}\n\t\tString type = decode(checkAllowed(segmentMatcher.group(1)));\n\t\tString value = decode(checkAllowed(segmentMatcher.group(2)));\n\t\treturn new Segment(type, value);\n\t}\n\n\tprivate String checkAllowed(String typeOrValue) {\n\t\tcheckDoesNotContain(typeOrValue, this.segmentDelimiter);\n\t\tcheckDoesNotContain(typeOrValue, this.typeValueSeparator);\n\t\tcheckDoesNotContain(typeOrValue, this.openSegment);\n\t\tcheckDoesNotContain(typeOrValue, this.closeSegment);\n\t\treturn typeOrValue;\n\t}\n\n\tprivate void checkDoesNotContain(String typeOrValue, char forbiddenCharacter) {\n\t\tPreconditions.condition(typeOrValue.indexOf(forbiddenCharacter) < 0,\n\t\t\t() -> \"type or value '%s' must not contain '%s'\".formatted(typeOrValue, forbiddenCharacter));\n\t}","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/junit-team/junit5/blob/956246301e03d757539f7b76dd5a91f298637563/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java#L79-L115","documentation":"Thrown by UniqueIdFormat.createSegment (line 94-102) when a single segment string fails to match the segment regex built from the open/typeValueSeparator/close delimiters (default '[', ':', ']'). UniqueId.parse (line 88) splits on '/' and parses each segment; any segment not matching the well-formed '[type:value]' pattern raises a JUnitException. This guards the integrity of the UniqueId segment format used throughout the engine.","triggerScenarios":"Calling UniqueId.parse on a malformed string, or selecting by UniqueId via a UniqueIdSelector built from a malformed string, where a segment lacks brackets, lacks the colon, has empty type or value, or contains stray delimiters. Common with copy-paste errors of test ids from logs/IDE.","commonSituations":"Passing a truncated UniqueId string (e.g. dropping the leading '['); using a logical display name instead of the machine segment; URL-decoding a segment incorrectly so delimiters reappear; building UniqueId strings by hand instead of via UniqueId.forEngine/append.","solutions":["Construct UniqueId values programmatically: UniqueId.forEngine(\"junit-jupiter\").append(\"test-class\", MyTest.class.getName()) instead of concatenating strings.","Verify the string shape: each segment must be '[' + type + ':' + value + ']', segments joined by '/'.","If the value contains ':', '[', ']', or '/', it must be URL-encoded (the format does this on output); ensure you pass already-formatted ids.","Copy the UniqueId verbatim from the failure report / launcher output rather than retyping it."],"exampleFix":"// before\nUniqueId id = UniqueId.parse(\"[engine:junit-jupiter]/MyTest#myTest\"); // '#' segment is malformed\n\n// after\nUniqueId id = UniqueId.parse(\"[engine:junit-jupiter]/[class:com.example.MyTest]/[method:myTest()]\");\n// or better, build it:\nUniqueId id = UniqueId.forEngine(\"junit-jupiter\")\n    .append(\"class\", \"com.example.MyTest\")\n    .append(\"method\", \"myTest()\");","handlingStrategy":"try-catch","validationCode":"static boolean isWellFormed(String id) {\n    if (id == null || id.isBlank()) return false;\n    return java.util.Arrays.stream(id.split(\"/\"))\n        .allMatch(s -> s.matches(\"\\\\[[^\\\\[\\\\]:]+:[^\\\\[\\\\]:]+\\\\]\"));\n}","typeGuard":null,"tryCatchPattern":"try {\n    return UniqueId.parse(raw);\n} catch (JUnitException e) {\n    throw new IllegalArgumentException(\"Invalid UniqueId string: \" + raw, e);\n}","preventionTips":["Build UniqueIds with UniqueId.forEngine(...).append(type, value) rather than string concatenation.","Copy UniqueIds verbatim from launcher output rather than retyping.","URL-encode segment values that may contain delimiters."],"tags":["junit-platform","unique-id","parsing","discovery"],"analyzedSha":"956246301e03d757539f7b76dd5a91f298637563","analyzedAt":"2026-08-04T19:25:17.049Z","schemaVersion":2}