quarkusio/quarkus · error · IllegalStateException
Cannot generate web links for the class because it is eithe
Error message
Cannot generate web links for the class because it is either missing an `id` field, a field with an `@Id` annotation or a field with a `@RestLinkId annotation
What it means
validateRec walks the entity class hierarchy looking for an `id` field, an @Id-annotated field, or a @RestLinkId field. If it exhausts the hierarchy (superName == null, i.e. java.lang.Object reached) without finding one, it throws this IllegalStateException — the class cannot be used for web links.
Source
Thrown at extensions/resteasy-reactive/rest-links/deployment/src/main/java/io/quarkus/resteasy/reactive/links/deployment/LinksProcessor.java:268
List<AnnotationInstance> fieldsAnnotatedWithRestLinkId = classInfo.fields().stream()
.flatMap(f -> f.annotations(RestLinkId.class).stream())
.toList();
// @RestLinkId annotation count > 1 is not allowed
if (fieldsAnnotatedWithRestLinkId.size() > 1) {
throw new IllegalStateException("Cannot generate web links for the class " + entityType +
" because it has multiple fields annotated with `@RestLinkId`, where a maximum of one is allowed");
}
// Id field found, break the loop
if (!fieldsNamedId.isEmpty() || !fieldsAnnotatedWithId.isEmpty() || !fieldsAnnotatedWithRestLinkId.isEmpty()) {
return;
}
// Id field not found and hope is gone
DotName superClassName = classInfo.superName();
if (superClassName == null) {
throw new IllegalStateException("Cannot generate web links for the class " + entityType +
" because it is either missing an `id` field, a field with an `@Id` annotation or a field with a `@RestLinkId annotation");
}
// Id field not found but there's still hope
classInfo = index.getClassByName(superClassName);
if (classInfo == null) {
throw new RuntimeException(String.format("Class '%s' was not found", superClassName));
}
validateRec(index, entityType, classInfo);
}
/**
* Implement a field getter inside a class and create an accessor class which knows how to access it.
*/
private void implementGetterWithAccessor(ClassOutput classOutput,
BuildProducer<BytecodeTransformerBuildItem> bytecodeTransformersProducer,
GetterMetadata getterMetadata) {
bytecodeTransformersProducer.produce(new BytecodeTransformerBuildItem(View on GitHub (pinned to e1c734241f)
Solutions
- Add a field named `id`, or annotate the identifier field with @RestLinkId (or @Id for JPA entities).
- If the class genuinely has no identity, do not generate links for it (disable rest-links for that resource).
- Check inheritance: if the id is on a mapped superclass, make sure the correct hierarchy is compiled in.
Example fix
// before class Item(var name: String) // after class Item(@RestLinkId var id: Long, var name: String)
Defensive patterns
Strategy: validation
Validate before calling
fun hasId(c: Class<*>): Boolean = c.fields.any { it.name == "id" ||
it.isAnnotationPresent(RestLinkId::class.java) || it.isAnnotationPresent(Id::class.java) } ||
(c.superclass?.let { hasId(it) } ?: false) Prevention
- Name the identifier field `id` or annotate it
- Don't reuse id-less DTOs for link generation
When it happens
Trigger: Registering/using an entity class for REST links that has no field named `id`, no @Id annotation, and no @RestLinkId annotation anywhere in its inheritance chain.
Common situations: DTOs or key-less records used as path parameters; entities using a composite key without @RestLinkId; renaming the id field to something else.
Related errors
- Cannot generate web links for the class because it has mult
- The @Blocking, @NonBlocking and @RunOnVirtualThread annotati
- Value not set for ${param}
- TransformedAnnotationsBuildItem#queryForMethodParam needs to
- @Compressed and @Uncompressed cannot be both declared on res
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/8d3a0a5614d9d019.
Report an issue: GitHub.