{"record":{"id":"fa19016171a6ffb3","repo":"quarkusio/quarkus","slug":"the-annotation-projectedfieldname-must-have-a-non","errorCode":null,"errorMessage":"The annotation ProjectedFieldName must have a non-empty value.","messagePattern":"The annotation ProjectedFieldName must have a non-empty value\\.","errorType":"exception","errorClass":"PanacheQueryException","httpStatus":null,"severity":"error","filePath":"extensions/panache/panache-hibernate-common/runtime/src/main/java/io/quarkus/panache/hibernate/common/runtime/ProjectionConstructorUtil.java","lineNumber":208,"sourceCode":"        return false;\n    }\n\n    private static boolean hasAnnotation(AnnotatedElement annotatedElement, String annotationTypeName) {\n        for (java.lang.annotation.Annotation annotation : annotatedElement.getAnnotations()) {\n            if (annotationTypeName.equals(annotation.annotationType().getName())) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    private static String getNameFromProjectedFieldName(AnnotatedElement annotatedElement) {\n        for (java.lang.annotation.Annotation annotation : annotatedElement.getAnnotations()) {\n            if (PROJECTED_FIELD_NAME_ANNOTATIONS.contains(annotation.annotationType().getName())) {\n                try {\n                    String name = (String) annotation.annotationType().getMethod(\"value\").invoke(annotation);\n                    if (name.isEmpty()) {\n                        throw new PanacheQueryException(\"The annotation ProjectedFieldName must have a non-empty value.\");\n                    }\n                    return name;\n                } catch (ReflectiveOperationException e) {\n                    throw new PanacheQueryException(\"Unable to read ProjectedFieldName value\", e);\n                }\n            }\n        }\n        throw new PanacheQueryException(\"Missing ProjectedFieldName annotation\");\n    }\n\n    private static String buildNoSuitableConstructorMessage(Class<?> type, Constructor<?> rejected) {\n        StringBuilder message = new StringBuilder(\"No suitable projection constructor found for \")\n                .append(type.getName())\n                .append(\" (rejected constructor: \")\n                .append(rejected)\n                .append(\").\");\n        if (isKotlinClass(type)) {\n            message.append(\" Kotlin value classes and default parameters may produce synthetic constructors.\")","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/panache/panache-hibernate-common/runtime/src/main/java/io/quarkus/panache/hibernate/common/runtime/ProjectionConstructorUtil.java#L190-L226","documentation":"getNameFromProjectedFieldName reads the value() member of a @ProjectedFieldName-style annotation found on a constructor parameter. If the annotation is present but its value is the empty string, Panache throws PanacheQueryException because an empty name cannot be mapped to any select item. This is a direct misuse of the annotation's contract that value must be a non-empty field name.","triggerScenarios":"Declaring @ProjectedFieldName(\"\") (or an aliased annotation whose value resolves to \"\") on a projection constructor parameter, then running a query that triggers projection construction.","commonSituations":"Placeholder left from code generation; programmatically built annotation values from config that resolved to empty; copy-paste where the value was deleted accidentally.","solutions":["Set the annotation value to the actual select item/attribute name: @ProjectedFieldName(\"fullName\")","If the parameter name already matches, remove the annotation entirely so the compiler-provided name is used","Add validation on dynamically generated DTOs to assert annotation values are non-empty"],"exampleFix":"// before\npublic PersonDto(@ProjectedFieldName(\"\") String name) { ... }\n\n// after\npublic PersonDto(@ProjectedFieldName(\"name\") String name) { ... }","handlingStrategy":"validation","validationCode":"static void assertProjectedFieldNameNonEmpty(java.lang.reflect.Parameter p) {\n    ProjectedFieldName a = p.getAnnotation(ProjectedFieldName.class);\n    if (a != null && a.value().isEmpty()) {\n        throw new IllegalStateException(\"@ProjectedFieldName on \" + p + \" must be non-empty\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    return query.project(Dto.class).list();\n} catch (PanacheQueryException e) {\n    if (e.getMessage().contains(\"non-empty value\")) {\n        throw new IllegalStateException(\"Fix empty @ProjectedFieldName values on \" + Dto.class, e);\n    }\n    throw e;\n}","preventionTips":["Never leave @ProjectedFieldName(\"\") placeholders; fill in the attribute name immediately","If the parameter name already matches the field, omit the annotation rather than using an empty value","Code-review DTO constructors for annotation completeness","Add an ArchUnit/startup check validating annotation values on projection DTOs"],"tags":["panache","jpa","annotation","projection","validation"],"backgroundTag":"invalid-annotation-value","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}