{"record":{"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/f070c699a08b5d8393df9afd147af5c5e90bb21b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java#L79-L115","documentation":"UniqueIdFormat.parse() splits a UniqueId string by the segment delimiter and runs each segment through createSegment(), which matches against the expected '[type:value]' pattern. If a segment does not match the format, a JUnitException is thrown. This is how the engine reports a malformed UniqueId during parsing.","triggerScenarios":"Calling UniqueId.forString / format.parse with a string whose segments are missing the '[type:value]' structure — unbalanced brackets, a missing type:value separator, or stray delimiters. Common when a UniqueId is hand-constructed, truncated, or corrupted (e.g. logged then copy-pasted with truncation).","commonSituations":"Passing a test id from a report/XML that was edited or truncated; building a selector from a fragment that is not a full UniqueId; copy-paste losing bracket characters; a tool that strips square brackets from logs.","solutions":["Use the full, unedited UniqueId string produced by UniqueId.toString() (e.g. from test reports) — do not hand-type or truncate it.","If you must construct one programmatically, use UniqueId.root(...).append(...) rather than string concatenation.","Round-trip-check: format.parse(id.toString()) should reproduce the id; if not, the source string is malformed.","Sanitize logs/tools that may strip the '[', ']', or ':' characters."],"exampleFix":"// before\nUniqueId id = UniqueId.forString(\"[engine:junit-jupiter]/MyTestClass\"); // second segment missing [type:value]\n// after\nUniqueId id = UniqueId.forString(\"[engine:junit-jupiter]/[class:com.example.MyTestClass]\");","handlingStrategy":"validation","validationCode":"// Validate a UniqueId string parses before using it.\nimport org.junit.platform.engine.UniqueId;\nString src = getIdFromExternalSource();\ntry {\n  UniqueId parsed = UniqueId.forString(src);\n} catch (org.junit.platform.commons.JUnitException e) {\n  throw new IllegalArgumentException(\"Not a valid UniqueId string: \" + src, e);\n}\n","typeGuard":"// A cheap structural guard before full parse: each segment must be [type:value].\nboolean looksLikeUniqueId(String s) {\n  if (s == null || s.isEmpty()) return false;\n  for (String seg : s.split(\"\\\\]/\\\\[|-/\")) { // rough split; rely on parse() for full validation\n    if (!seg.matches(\".*:.*\")) return false;\n  }\n  return s.contains(\"[\") && s.contains(\"]\") && s.contains(\":\");\n}","tryCatchPattern":"try { UniqueId id = UniqueId.forString(raw); } catch (org.junit.platform.commons.JUnitException e) { /* log raw, fall back to a broader selector */ }","preventionTips":["Always source UniqueId strings from UniqueId.toString() output, never hand-typed.","Build UniqueIds with UniqueId.root(...).append(...) rather than string concatenation.","Sanitize report/log tooling so brackets and colons survive copy-paste."],"tags":["uniqueid","parsing","engine","discovery"],"backgroundTag":null,"analyzedSha":"f070c699a08b5d8393df9afd147af5c5e90bb21b","analyzedAt":"2026-08-11T20:31:00.530Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}