quarkusio/quarkus · error · IllegalStateException
Unable to construct type for ${decorator}: ${e.getMessage()}
Error message
Unable to construct type for ${decorator}: ${e.getMessage()} What it means
While generating the decorator's proxy class constructor, Arc converts each @Decorates decorated type into a runtime Type via RuntimeTypeCreator. If conversion fails (the IllegalArgumentException case) - typically because a type argument cannot be resolved to a loadable class - the generator aborts with this IllegalStateException.
Source
Thrown at independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/DecoratorGenerator.java:203
for (AnnotationInstance delegateQualifier : decorator.getDelegateQualifiers()) {
ClassInfo delegateQualifierClass = decorator.getDeployment()
.getQualifier(delegateQualifier.name());
bc.withSet(delegateQualifiers).add(
annotationLiterals.create(bc, delegateQualifierClass, delegateQualifier));
}
bc.set(cc.this_().field(delegateQualifiersField), delegateQualifiers);
}
LocalVar tccl = bc.localVar("tccl", bc.invokeVirtual(MethodDescs.THREAD_GET_TCCL, bc.currentThread()));
RuntimeTypeCreator rttc = RuntimeTypeCreator.of(bc).withTCCL(tccl);
LocalVar decoratedTypes = bc.localVar("decoratedTypes", bc.new_(HashSet.class));
for (Type decoratedType : decorator.getDecoratedTypes()) {
try {
bc.withSet(decoratedTypes).add(rttc.create(decoratedType));
} catch (IllegalArgumentException e) {
throw new IllegalStateException("Unable to construct type for " + decorator
+ ": " + e.getMessage());
}
}
bc.set(cc.this_().field(decoratedTypesField), decoratedTypes);
LocalVar delegateType;
try {
delegateType = rttc.create(decorator.getDelegateType());
} catch (IllegalArgumentException e) {
throw new IllegalStateException("Unable to construct type for " + decorator
+ ": " + e.getMessage());
}
bc.set(cc.this_().field(delegateTypeField), delegateType);
});
}
static boolean isAbstractDecoratorImpl(BeanInfo bean, String providerTypeName) {
return bean.isDecorator() && ((DecoratorInfo) bean).isAbstract() && providerTypeName.endsWith(ABSTRACT_IMPL_SUFFIX);View on GitHub (pinned to e1c734241f)
Solutions
- Ensure all classes used in the decorated type's generic signature are on the application classpath
- Clean rebuild to refresh the bean archive index
- Simplify the decorated type's generic parameters (use concrete resolvable types)
- Check the decorator's delegate/decorated types for typos in type arguments
Example fix
// before
class MyDecorator implements Converter<SomeMissingClass> { @Decorates ... }
// after
class MyDecorator implements Converter<String> { @Decorates ... } Defensive patterns
Strategy: validation
Validate before calling
// ensure decorated type raw class is loadable before decorating
static void checkDecoratedType(Class<?> decorated) {
if (!decorated.isInterface()) throw new IllegalArgumentException("Must be interface: " + decorated);
for (var t : decorated.getTypeParameters()) System.out.println("type param needs resolvable arg: " + t);
} Prevention
- Keep decorated interface type arguments concrete and on the classpath
- Clean rebuild after refactoring generic interfaces
When it happens
Trigger: A decorator's decorated type (from the interface it implements with @Decorates) uses parameterized types whose raw classes are missing/unloadable in the application index or TCCL during decorator class generation.
Common situations: Decorating a generic interface whose type arguments reference a class that was removed or is in a dependency not on the runtime classpath; split-package/classloading issues in fast-jar.
Related errors
- Unable to construct type for ${btRemovedBean}: ${e.getMessag
- Decorated type not found in the bean archive index: ${decora
- The decorator ${decoratorClass} has no @Delegate injection p
- The decorator ${decoratorClass} has multiple @Delegate injec
- A decorator must be @Dependent but ${decoratorClass} declare
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/94bb3e420574ec92.
Report an issue: GitHub.