quarkusio/quarkus · error · BuildException
Extra steps left over
Error message
Extra steps left over
What it means
RootResource.posts (POST, text/plain) throws "No post data" when the JAX-RS request entity resolves to null. This happens when the POST body is absent, empty, or has a Content-Type inconsistent with @Consumes(TEXT_PLAIN), so the String parameter is never populated.
Source
Thrown at core/builder/src/main/java/io/quarkus/builder/Execution.java:149
intr = true;
} finally {
if (intr)
Thread.currentThread().interrupt();
}
for (Diagnostic diagnostic : diagnostics) {
if (diagnostic.getLevel() == Diagnostic.Level.ERROR) {
BuildException failed = new BuildException("Build failed due to errors", diagnostic.getThrown(),
Collections.unmodifiableList(diagnostics));
for (Diagnostic i : diagnostics) {
if (i.getThrown() != null && i.getThrown() != diagnostic.getThrown()) {
failed.addSuppressed(i.getThrown());
}
}
throw failed;
}
}
if (lastStepCount.get() > 0)
throw new BuildException("Extra steps left over", Collections.emptyList());
long duration = max(0, System.nanoTime() - start);
metrics.buildFinished(TimeUnit.NANOSECONDS.toMillis(duration));
return new BuildResult(singles, multis, finalIds, Collections.unmodifiableList(diagnostics),
duration, metrics, chain.getClassLoader());
}
EnhancedQueueExecutor getExecutor() {
return executor;
}
String getBuildTargetName() {
return buildTargetName;
}
void setErrorReported() {
errorReported.compareAndSet(false, true);
}View on GitHub (pinned to e1c734241f)
Solutions
- Send a non-empty text/plain body with the POST request (e.g. curl -H 'Content-Type: text/plain' -d 'payload' ...).
- Ensure the Content-Type header is text/plain to match @Consumes.
- Null-check data before use and return 400 instead of RuntimeException.
- Verify no filter/proxy removes the request body.
Example fix
// before
public String posts(String data, @Context SecurityContext sec) {
if (data == null) {
throw new RuntimeException("No post data");
}
// after
curl -H "Content-Type: text/plain" -d "hello" http://localhost:8080/
// and/or in code: return Response.status(400).build() when data == null Defensive patterns
Strategy: validation
Validate before calling
if (fruit.getId() != null) {
fruit = new Fruit(fruit.getName()); // drop id before POST
}
given().contentType(ContentType.JSON).body(fruit).post("/fruits"); Type guard
static Fruit withoutId(Fruit f) {
return f.getId() == null ? f : new Fruit(f.getName());
} Try / catch
try {
given().body(fruit).post("/fruits");
} catch (WebApplicationException e) {
if (e.getResponse().getStatus() == 422) { fruit.setId(null); /* retry POST */ }
else throw e;
} Prevention
- Use a create-DTO without an id field for POST bodies
- Never re-POST an entity fetched via GET; clone it and null the id
- Distinguish POST (create) vs PUT (update) semantics in clients
- Assert 201 (not 422) in tests that create fruit
When it happens
Trigger: POST to the resource with an empty body, no body at all, or a Content-Type other than text/plain (e.g. none or application/json), causing data == null.
Common situations: Test client sending POST without a body; curl forgetting -d or -H 'Content-Type: text/plain'; framework/quarkus-rest clients serializing nothing; gateway stripping the body.
Related errors
- Unknown start character for json value: %s
- Currently only 'fruitsFindBy?type=name' is supported
- Currently only 'fruitsFindBy?type=name' is supported
- Currently only 'fruitsFindBy?type=name' is supported
- Id was invalidly set on request.
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/4d5ea975ec8f582f.
Report an issue: GitHub.