quarkusio/quarkus · error · UnsupportedOperationException
Cannot construct empty build items
Error message
Cannot construct empty build items
What it means
EmptyBuildItem represents a build item used only as a signal, consumed/produced via @Consume/@Produce without an actual instance. Its (protected) constructor unconditionally throws UnsupportedOperationException, so any attempt to directly instantiate an EmptyBuildItem subclass fails with "Cannot construct empty build items". It is a deliberate API guard, not a runtime fault.
Source
Thrown at core/builder/src/main/java/io/quarkus/builder/item/EmptyBuildItem.java:12
package io.quarkus.builder.item;
/**
* An empty build item. Empty build items carry no data and may be used, for example, for ordering and for
* running steps which don't otherwise produce anything.
*
* Empty build items cannot be instantiated, you must use <code>@Produce(MyEmptyBuildItem.class)</code> or
* <code>@Consume(MyEmptyBuildItem.class)</code> instead of the standard ways to consume or produce build items.
*/
public abstract class EmptyBuildItem extends BuildItem {
protected EmptyBuildItem() {
throw new UnsupportedOperationException("Cannot construct empty build items");
}
}
View on GitHub (pinned to e1c734241f)
Solutions
- Do not instantiate it: reference the class literal in annotations, e.g. @BuildStep @Produce(MyEmptyBuildItem.class) ... or declare the item type as a build-step parameter for consumption.
- If the step must actually produce a value-bearing item, switch the class to extend BuildItem (non-empty) and return a real instance.
- Remove any `new MyEmptyBuildItem()` calls, including in tests and reflection-based code.
- For pure ordering, produce/consume via @Produce/@Consume annotations or MultiBuildItem-free signal types exactly as the class Javadoc describes.
Example fix
// before
@BuildStep
void produceSignal() { new MySignalItem(); }
// after
@BuildStep
@Produce(MySignalItem.class)
void produceSignal() { /* no instance needed */ } Defensive patterns
Strategy: validation
Validate before calling
// never instantiate; assert usage in tests
static void assertNotInstantiated(Class<? extends EmptyBuildItem> clazz) {
// only the class literal should be referenced:
// @Produce(clazz) / @Consume(clazz) / method parameters of type clazz
} Type guard
static <T extends EmptyBuildItem> T neverCreate(Class<T> clazz) {
throw new UnsupportedOperationException(
clazz + " is an EmptyBuildItem: use @Produce/@Consume(" + clazz.getSimpleName() + ".class), not new");
} Try / catch
try {
processSignal();
} catch (UnsupportedOperationException e) {
if (e.getMessage().equals("Cannot construct empty build items")) {
throw new IllegalStateException("Replace direct construction of " + MySignalItem.class.getSimpleName()
+ " with @Produce/@Consume class references", e);
}
throw e;
} Prevention
- Reference empty build items only via class literals in @Produce/@Consume or as build-step parameter types
- Grep for `new` on EmptyBuildItem subclasses during code review
- If the item must carry data, extend BuildItem instead of EmptyBuildItem
When it happens
Trigger: Calling `new MyEmptyBuildItem()` (or via reflection/serialization) on a class extending EmptyBuildItem instead of referencing the class object in @Produce(MyEmptyBuildItem.class) or @Consume(MyEmptyBuildItem.class); a build step method that tries to return a new instance of an empty item.
Common situations: Misunderstanding the empty build item idiom when writing build steps; code generators or tests constructing instances generically; migrating a normal build item to EmptyBuildItem while leaving old `new` call sites in place.
Related errors
- A generic type is not allowed here; try creating a subclass
- Build item class must be leaf (final) types: %s
- A build step must be a non-static method: %s
- You have to specify a key. This is the key the user will pre
- You have to specify a description. This is what the user wil
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/5d4ab1e1101724cd.
Report an issue: GitHub.