{"id":"10ecadcb6bbc818a","repo":"junit-team/junit5","slug":"configuration-error-error","errorCode":null,"errorMessage":"Configuration error: <error>.","messagePattern":"Configuration error: <error>\\.","errorType":"exception","errorClass":"PreconditionViolationException","httpStatus":null,"severity":"error","filePath":"junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java","lineNumber":386,"sourceCode":"\t\t\t\t\tparameterName(actualDeclaration), parameterIndex));\n\t\t\t}\n\t\t\telse if (errors.isEmpty()) {\n\t\t\t\tparameterDeclarationMapping.put(actualDeclaration, originalDeclaration);\n\t\t\t}\n\t\t}\n\t\treturn errors;\n\t}\n\n\tprivate static String parameterName(ParameterDeclaration actualDeclaration) {\n\t\treturn actualDeclaration.getParameterName().map(name -> \" '\" + name + \"'\").orElse(\"\");\n\t}\n\n\tprivate static <T> T configurationErrorOrSuccess(List<String> errors, Supplier<T> successfulResult) {\n\t\tif (errors.isEmpty()) {\n\t\t\treturn successfulResult.get();\n\t\t}\n\t\telse if (errors.size() == 1) {\n\t\t\tthrow new PreconditionViolationException(\"Configuration error: \" + errors.get(0) + \".\");\n\t\t}\n\t\telse {\n\t\t\tthrow new PreconditionViolationException(\"%d configuration errors:%n%s\".formatted(errors.size(),\n\t\t\t\terrors.stream().collect(joining(lineSeparator() + \"- \", \"- \", \"\"))));\n\t\t}\n\t}\n\n\tprivate static void validateIndexedParameters(\n\t\t\tNavigableMap<Integer, List<FieldParameterDeclaration>> indexedParameters, List<String> errors) {\n\n\t\tif (indexedParameters.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\n\t\tindexedParameters.forEach(\n\t\t\t(index, declarations) -> validateIndexedParameterDeclarations(index, declarations, errors));\n\n\t\tfor (int index = 0; index <= indexedParameters.lastKey(); index++) {","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/junit-team/junit5/blob/956246301e03d757539f7b76dd5a91f298637563/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java#L368-L404","documentation":"Thrown by ResolverFacade.configurationErrorOrSuccess() when exactly one validation error is found during @ParameterizedClass field declaration validation or lifecycle method parameter validation. The errors include: duplicate @Parameter indices, negative @Parameter indices, final @Parameter fields, missing sequential indices, or incompatible lifecycle method parameters. The single error is wrapped as 'Configuration error: <error>.'","triggerScenarios":"Exactly one misconfiguration in a @ParameterizedClass using @Parameter fields: a @Parameter field declared final, two fields with the same @Parameter(index), a @Parameter(-1) on a non-aggregator, a gap in @Parameter indices (e.g., @Parameter(0) and @Parameter(2) with no @Parameter(1)), or a single lifecycle method parameter incompatibility.","commonSituations":"Declaring @Parameter fields as final (common when using Lombok or records). Skipping an index in a sequence of @Parameter fields. An @AfterEach/@BeforeEach method in a @ParameterizedClass declaring a parameter type incompatible with the class parameter.","solutions":["Read the specific error message after 'Configuration error:' — it identifies the exact field and problem","Make @Parameter fields non-final (remove final keyword or Lombok val/final annotations)","Ensure @Parameter indices are sequential starting from 0 with no gaps","Ensure lifecycle methods (@BeforeEach, @AfterEach, etc.) parameter types match the @ParameterizedClass constructor or field types"],"exampleFix":"// before\n@ParameterizedClass\n@CsvSource(\"1, 2\")\nclass MyTest {\n    @Parameter(0) final int a; // final is not allowed\n    @Parameter(1) int b;\n    MyTest() { }\n}\n\n// after\n@ParameterizedClass\n@CsvSource(\"1, 2\")\nclass MyTest {\n    @Parameter(0) int a; // remove final\n    @Parameter(1) int b;\n    MyTest() { }\n}","handlingStrategy":"validation","validationCode":"// Validate @Parameter field declarations at setup time:\nstatic void validateParameterFields(Class<?> testClass) {\n    Set<Integer> indices = new HashSet<>();\n    for (Field f : testClass.getDeclaredFields()) {\n        Parameter p = f.getAnnotation(Parameter.class);\n        if (p == null) continue;\n        if (Modifier.isFinal(f.getModifiers()))\n            throw new IllegalStateException(\"@Parameter field \" + f + \" must not be final\");\n        if (!indices.add(p.value()))\n            throw new IllegalStateException(\"Duplicate @Parameter(\" + p.value() + \")\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never declare @Parameter fields as final","Ensure @Parameter indices are sequential: 0, 1, 2, ... with no gaps","Do not duplicate @Parameter index values across fields","Run a quick IDE search for '@Parameter' annotations to review field declarations"],"tags":["parameterized-class","field-injection","configuration","validation","junit-jupiter-params"],"analyzedSha":"956246301e03d757539f7b76dd5a91f298637563","analyzedAt":"2026-08-04T19:25:17.049Z","schemaVersion":2}