{"record":{"id":"a8462cc2d71d439d","repo":"junit-team/junit5","slug":"failed-to-format-display-name-for-parameterized-te","errorCode":null,"errorMessage":"Failed to format display name for parameterized test. See nested exception for further details.","messagePattern":"Failed to format display name for parameterized test\\. See nested exception for further details\\.","errorType":"exception","errorClass":"JUnitException","httpStatus":null,"severity":"error","filePath":"junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java","lineNumber":105,"sourceCode":"\t\t\tParameterizedDeclarationContext<?> declarationContext, int argumentMaxLength) {\n\t\ttry {\n\t\t\tthis.partialFormatters = parse(pattern, displayName, declarationContext, argumentMaxLength);\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tString message = \"The display name pattern defined for the parameterized test is invalid. \"\n\t\t\t\t\t+ \"See nested exception for further details.\";\n\t\t\tthrow new JUnitException(message, ex);\n\t\t}\n\t}\n\n\tString format(int invocationIndex, EvaluatedArgumentSet arguments, boolean quoteTextArguments) {\n\t\ttry {\n\t\t\treturn formatSafely(invocationIndex, arguments, quoteTextArguments);\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tString message = \"Failed to format display name for parameterized test. \"\n\t\t\t\t\t+ \"See nested exception for further details.\";\n\t\t\tthrow new JUnitException(message, ex);\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"JdkObsolete\")\n\tprivate String formatSafely(int invocationIndex, EvaluatedArgumentSet arguments, boolean quoteTextArguments) {\n\t\tArgumentsContext context = new ArgumentsContext(invocationIndex, arguments.getConsumedArguments(),\n\t\t\targuments.getName(), quoteTextArguments);\n\t\tStringBuffer result = new StringBuffer(); // used instead of StringBuilder so MessageFormat can append directly\n\t\tfor (PartialFormatter partialFormatter : this.partialFormatters) {\n\t\t\tpartialFormatter.append(context, result);\n\t\t}\n\t\treturn result.toString();\n\t}\n\n\tprivate PartialFormatter[] parse(String pattern, String displayName,\n\t\t\tParameterizedDeclarationContext<?> declarationContext, int argumentMaxLength) {\n\n\t\tList<PartialFormatter> result = new ArrayList<>();","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/junit-team/junit5/blob/f070c699a08b5d8393df9afd147af5c5e90bb21b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java#L87-L123","documentation":"Thrown at runtime (during actual test invocation) when formatting the display name fails, as opposed to error 47 which fails at parse time. The format() method calls formatSafely() which iterates through the PartialFormatter segments and appends to a StringBuffer. If a formatter fails — e.g., a MessageFormat placeholder references argument index {5} but only 3 arguments were provided — the exception is wrapped in this JUnitException with the original cause.","triggerScenarios":"The display name pattern references more arguments than are actually supplied for a particular invocation. For example, @ParameterizedTest(name=\"{0} {1} {2}\") but an Arguments source provides only 2 values for some invocations. An ArgumentSet with fewer columns than the pattern expects.","commonSituations":"Parameterized tests with variable-length argument sets (some rows have more columns than others). Display name patterns designed for the maximum argument count but some sources provide fewer. CSV sources with ragged rows where some lines have fewer fields. Custom Arguments providers with inconsistent argument counts.","solutions":["Ensure all argument sets provide a consistent number of arguments that matches the display name pattern's placeholders","Use the {arguments} or {arguments-with-names} placeholder which adapts to the actual argument count, rather than fixed indices like {0}, {1}","Inspect the nested cause for the specific index or formatting error","Validate argument set shapes in your ArgumentsProvider before returning them"],"exampleFix":"// before — pattern expects 3 args but some rows have 2\n@ParameterizedTest(name = \"{0} {1} {2}\")\n@CsvSource({ \"a,b,c\", \"d,e\" })\nvoid test(String x, String y, String z) { }\n\n// after — use adaptive placeholder\n@ParameterizedTest(name = \"#{index} {arguments}\")\n@CsvSource({ \"a,b,c\", \"d,e\" })\nvoid test(String x, String y, @Parameter(values = \"default\") String z) { }","handlingStrategy":"validation","validationCode":"// Validate that all argument sets have enough values for the display name pattern\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nstatic int maxPlaceholderIndex(String pattern) {\n    Pattern p = Pattern.compile(\"\\\\{(\\\\d+)\");\n    Matcher m = p.matcher(pattern);\n    int max = -1;\n    while (m.find()) {\n        max = Math.max(max, Integer.parseInt(m.group(1)));\n    }\n    return max;\n}\n\n// Ensure: every Arguments set has at least (maxPlaceholderIndex + 1) values\n// If not, use {arguments} instead of {0}, {1}, etc.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer {arguments} or {arguments-with-names} over fixed-index placeholders ({0}, {1}) for variable-length argument sets","Ensure all argument sets from a source have consistent column counts","When using ragged CSV data, map optional columns via @Parameter(values=\"default\") rather than positional access"],"tags":["display-name","runtime","messageformat","argument-mismatch","junit-params"],"backgroundTag":null,"analyzedSha":"f070c699a08b5d8393df9afd147af5c5e90bb21b","analyzedAt":"2026-08-11T20:31:00.530Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}