quarkusio/quarkus · error · PanacheQueryException
Missing ProjectedFieldName annotation
Error message
Missing ProjectedFieldName annotation
What it means
getNameFromProjectedFieldName iterates a parameter's annotations looking for one whose type name is in PROJECTED_FIELD_NAME_ANNOTATIONS; if none is found it throws PanacheQueryException("Missing ProjectedFieldName annotation"). This indicates Panache needed an explicit field-name mapping (typically because parameter names are not compiled in) but the required annotation was absent on that parameter.
Source
Thrown at extensions/panache/panache-hibernate-common/runtime/src/main/java/io/quarkus/panache/hibernate/common/runtime/ProjectionConstructorUtil.java:216
}
return false;
}
private static String getNameFromProjectedFieldName(AnnotatedElement annotatedElement) {
for (java.lang.annotation.Annotation annotation : annotatedElement.getAnnotations()) {
if (PROJECTED_FIELD_NAME_ANNOTATIONS.contains(annotation.annotationType().getName())) {
try {
String name = (String) annotation.annotationType().getMethod("value").invoke(annotation);
if (name.isEmpty()) {
throw new PanacheQueryException("The annotation ProjectedFieldName must have a non-empty value.");
}
return name;
} catch (ReflectiveOperationException e) {
throw new PanacheQueryException("Unable to read ProjectedFieldName value", e);
}
}
}
throw new PanacheQueryException("Missing ProjectedFieldName annotation");
}
private static String buildNoSuitableConstructorMessage(Class<?> type, Constructor<?> rejected) {
StringBuilder message = new StringBuilder("No suitable projection constructor found for ")
.append(type.getName())
.append(" (rejected constructor: ")
.append(rejected)
.append(").");
if (isKotlinClass(type)) {
message.append(" Kotlin value classes and default parameters may produce synthetic constructors.")
.append(" Use @ProjectedConstructor, @ProjectedFieldName, or a DTO with plain property types such as Long.");
} else {
message.append(" Use @ProjectedConstructor or @ProjectedFieldName to select a usable constructor,")
.append(" and ensure the application is built with parameter names (-parameters).");
}
return message.toString();
}
View on GitHub (pinned to e1c734241f)
Solutions
- Annotate every constructor parameter with @ProjectedFieldName("entityFieldName")
- Rebuild the application with -parameters so annotations are not strictly required
- Ensure annotations are placed on constructor parameters, not class fields
- Rebuild all modules of the DTO after adding annotations (stale classes keep the error)
Example fix
// before
public PersonDto(String name, @ProjectedFieldName("age") int years) { ... }
// after
public PersonDto(@ProjectedFieldName("name") String name, @ProjectedFieldName("age") int years) { ... } Defensive patterns
Strategy: validation
Validate before calling
static void assertAllParametersAnnotated(java.lang.reflect.Constructor<?> c) {
for (java.lang.reflect.Parameter p : c.getParameters()) {
if (!p.isNamePresent() && !p.isAnnotationPresent(ProjectedFieldName.class)) {
throw new IllegalStateException("Parameter " + p + " needs @ProjectedFieldName or compile with -parameters");
}
}
} Try / catch
try {
return query.project(Dto.class).list();
} catch (PanacheQueryException e) {
if (e.getMessage().contains("Missing ProjectedFieldName")) {
throw new IllegalStateException("Annotate all parameters of " + Dto.class + " constructor", e);
}
throw e;
} Prevention
- When adding @ProjectedFieldName, annotate every constructor parameter, not just some
- Rebuild the whole project after adding annotations so stale classes don't linger
- Enable -parameters as the primary mechanism and use annotations only where names differ
- Put annotations on constructor parameters, not on fields
When it happens
Trigger: A constructor parameter without @ProjectedFieldName reaching the name-resolution path where reflection cannot supply a name — i.e. class compiled without -parameters and no other name source, so the fallback demands the annotation and fails when missing.
Common situations: Annotating only some constructor parameters and missing one; applying the annotation to fields instead of constructor parameters; classpath mismatch where an old compiled DTO lacks both -parameters and annotations.
Related errors
- Unable to read ProjectedFieldName value
- No suitable projection constructor found for ${type.getName(
- Your application must be built with parameter names, this sh
- The annotation ProjectedFieldName must have a non-empty valu
- No suitable projection constructor found for ${type.getName(
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/82e162797e39f3a9.
Report an issue: GitHub.