quarkusio/quarkus · error · ChainBuildException
No producers for required item %s, step builder used: %s
Error message
No producers for required item %s, step builder used: %s
What it means
This integration-test servlet throws RuntimeException("principal was null") in doGet when the security check on the principal name fails. Despite the message, the code actually calls req.getUserPrincipal().getName() — a NullPointerException occurs here if getUserPrincipal() returns null (unauthenticated request). It signals that the request reached the servlet without an authenticated principal, i.e. Elytron security did not authenticate/propagate the identity as the test expects.
Source
Thrown at core/builder/src/main/java/io/quarkus/builder/BuildChainBuilder.java:196
private Map<BuildStepBuilder, Set<Produce>> wireDependencies(Set<BuildStepBuilder> included)
throws ChainBuildException {
Map<ItemId, List<Produce>> allProduces = extractProducers();
final ArrayDeque<BuildStepBuilder> toAdd = new ArrayDeque<>(); // the queue of steps to be added
for (ItemId finalId : finalIds) {
addItem(allProduces, included, toAdd, finalId);
}
// now recursively add producers of consumed items
Map<BuildStepBuilder, Set<Produce>> dependencies = new LinkedHashMap<>();
BuildStepBuilder stepBuilder;
while ((stepBuilder = toAdd.pollFirst()) != null) {
for (Map.Entry<ItemId, Consume> entry : stepBuilder.getConsumes().entrySet()) {
final Consume consume = entry.getValue();
final ItemId id = entry.getKey();
if (!consume.flags().contains(ConsumeFlag.OPTIONAL) && !id.isMulti()) {
if (!initialIds.contains(id) && !allProduces.containsKey(id)) {
throw new ChainBuildException(
"No producers for required item " + id + ", step builder used: " + stepBuilder);
}
}
// add every producer
addItem(allProduces, included, toAdd, id,
dependencies.computeIfAbsent(stepBuilder, x -> new LinkedHashSet<>()));
}
}
return dependencies;
}
private Map<ItemId, List<Produce>> extractProducers() throws ChainBuildException {
final Map<ItemId, List<Produce>> allProduces = new LinkedHashMap<>();
for (Map.Entry<BuildStepBuilder, StackTraceElement[]> stepEntry : steps.entrySet()) {
final BuildStepBuilder stepBuilder = stepEntry.getKey();
final Map<ItemId, Produce> stepProduces = stepBuilder.getProduces();
for (Map.Entry<ItemId, Produce> entry : stepProduces.entrySet()) {
final ItemId id = entry.getKey();View on GitHub (pinned to e1c734241f)
Solutions
- Send valid credentials with the request (e.g. basic auth user/password configured in application.properties for the elytron test realm).
- Verify application.properties configures quarkus.http.auth.permission.* policies requiring authentication for /* and a working elytron identity mapping.
- Check that @ServletSecurity or web.xml constraints require roles so Undertow/Elytron authenticates before doGet runs.
- Guard the code: check req.getUserPrincipal() for null before calling getName().
Example fix
// before
if (req.getUserPrincipal().getName() == null) {
throw new RuntimeException("principal was null");
}
// after
if (req.getUserPrincipal() == null) {
throw new RuntimeException("principal was null");
} Defensive patterns
Strategy: validation
Validate before calling
Response r = given().header("tenantId", tenant).get("/fruits/" + id);
if (r.getStatusCode() == 404) {
throw new SkipException("Fruit " + id + " not present in tenant " + tenant);
} Try / catch
try {
given().header("tenantId", tenant).body(fruit).put("/fruits/" + id);
} catch (WebApplicationException e) {
if (e.getResponse().getStatus() == 404) { /* recreate or skip */ }
else throw e;
} Prevention
- Always send the correct tenant header for multi-tenant endpoints
- Resolve ids from POST/GET responses instead of hard-coding them
- Treat 404 on PUT as a state error and recreate the resource
- Verify test seed data in the target tenant before update calls
When it happens
Trigger: An unauthenticated GET request reaches /* in the elytron-undertow integration test: the security domain/auth mechanism did not run or failed, so getUserPrincipal() is null and .getName() throws; or a principal whose getName() returns null is attached.
Common situations: Missing or wrong Authorization header/basic-auth credentials in the test request; quarkus.http.auth.* permission config allowing the path anonymously when it should require a role; elytron properties-file identity config missing so no user is authenticated; calling the endpoint through a proxy/filter that strips security context.
Related errors
- cycle detection failure report (dynamic CycleBuildException
- Build step '%s' does not produce any build item and thus wil
- Cannot consume/produce interface or abstract class build ite
- AuthenticationFailedException
- AuthenticationFailedException
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/9171abf18e7a58d5.
Report an issue: GitHub.