{"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/956246301e03d757539f7b76dd5a91f298637563/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java#L87-L123","documentation":"Thrown by ParameterizedInvocationNameFormatter.format() during each test invocation when formatting the display name with actual argument values throws an exception. Unlike error 47 (which is a parse-time pattern error), this occurs at runtime when MessageFormat.format() fails on the real argument values.","triggerScenarios":"The display name pattern is syntactically valid but a MessageFormat sub-segment fails when applied to the actual argument values — e.g., a {0,number,currency} format applied to a non-numeric argument, or a format specifier that conflicts with the runtime type of an argument.","commonSituations":"A @ParameterizedTest with name = \"{0,number,#.##}\" but one of the CSV argument rows contains a non-numeric string. An argument type changes between rows causing some invocations to format fine and others to fail. Using a MessageFormat type specifier incompatible with the argument's actual type.","solutions":["Review the nested exception to find which argument and format specifier caused the failure","Simplify the name pattern to plain JUnit placeholders ({index}, {arguments}) to avoid MessageFormat type conflicts","Ensure all argument rows provide values compatible with any MessageFormat type specifiers in the pattern","If mixing types across invocations, remove the specific format type (e.g., ,number) and use a plain {0} placeholder"],"exampleFix":"// before\n@ParameterizedTest(name = \"{0,number,currency}\")\n@CsvSource({ \"1.50\", \"N/A\" })\nvoid test(String val) { }\n\n// after (no type-specific MessageFormat on mixed-type arguments)\n@ParameterizedTest(name = \"{0}\")\n@CsvSource({ \"1.50\", \"N/A\" })\nvoid test(String val) { }","handlingStrategy":"validation","validationCode":"// Ensure argument values are compatible with any MessageFormat specifiers:\n@ParameterizedTest(name = \"{0}\") // safe for all types\n@CsvSource({\"1\", \"text\"})\nvoid test(String val) { }\n// If using {0,number,...}, ensure all rows provide compatible types","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid MessageFormat type specifiers (e.g., {0,number,currency}) when argument types vary across invocations","Use plain placeholders ({0}, {arguments}) that work with any argument type","Test the display name pattern with all representative argument rows, not just the first","Check the nested exception for the specific MessageFormat.format failure"],"tags":["parameterized-test","display-name","messageformat","runtime-error","junit-jupiter-params"],"analyzedSha":"956246301e03d757539f7b76dd5a91f298637563","analyzedAt":"2026-08-04T19:25:17.049Z","schemaVersion":2}