eclipse-vertx/vert.x · error · DecodeException
Unexpected trailing token
Error message
Unexpected trailing token
What it means
After Jackson successfully binds a value in DatabindCodec.fromParser, the codec calls parser.nextToken() to confirm the stream ends. If another token remains (extra JSON content after the first value), it throws DecodeException('Unexpected trailing token'). This enforces that input contains exactly one JSON value with nothing after it.
Source
Thrown at vertx-core/src/main/java21/io/vertx/core/json/jackson/v3/DatabindCodec.java:114
}
public static JsonParser createParser(String str) {
return DatabindCodec.mapper.createParser(str);
}
public static <T> T fromParser(JsonParser parser, Class<T> type) throws DecodeException {
T value;
JsonToken remaining;
try {
value = DatabindCodec.mapper.readValue(parser, type);
remaining = parser.nextToken();
} catch (Exception e) {
throw new DecodeException("Failed to decode:" + e.getMessage(), e);
} finally {
close(parser);
}
if (remaining != null) {
throw new DecodeException("Unexpected trailing token");
}
if (type == Object.class) {
value = (T) adapt(value);
}
return value;
}
private static <T> T fromParser(JsonParser parser, TypeReference<T> type) throws DecodeException {
T value;
try {
value = DatabindCodec.mapper.readValue(parser, type);
} catch (Exception e) {
throw new DecodeException("Failed to decode:" + e.getMessage(), e);
} finally {
close(parser);
}
if (type.getType() == Object.class) {
value = (T) adapt(value);View on GitHub (pinned to fb308bd8c3)
Solutions
- Split the input and decode one JSON document at a time (e.g. split on lines for NDJSON and call decodeValue per line).
- Trim/sanitize the payload so only one JSON value remains.
- Fix the producer that is concatenating JSON documents.
- If multi-document input is expected, use Jackson's MappingIterator via mapper.readValues(parser, type) instead of single-value decode.
Example fix
// before
JsonObject o = Json.decodeValue(ndjsonBuffer, JsonObject.class); // two lines -> fails
// after
JsonObject o = Json.decodeValue(ndjsonBuffer.toString().split("\n")[0], JsonObject.class); Defensive patterns
Strategy: validation
Validate before calling
boolean singleJsonDocument(String s) {
String t = s.trim();
// quick sanity: first non-space char opens, last closes, and lengths plausibly match one doc
return t.startsWith("{") || t.startsWith("[") || t.startsWith("\"") || t.matches("^-?\\d.*") || t.equals("true") || t.equals("false") || t.equals("null");
} Try / catch
try {
JsonObject o = Json.decodeValue(buf, JsonObject.class);
} catch (DecodeException e) {
if (e.getMessage().contains("trailing token")) {
// split and decode each document separately
}
} Prevention
- Never feed NDJSON/multi-document streams to a single-value decoder; split first.
- Ensure producers emit exactly one JSON document per message.
- Concatenate buffers only after confirming they form a single document.
When it happens
Trigger: Json.decodeValue on input containing concatenated values like '{}{}' or '[1,2] extra', or newline-delimited JSON (NDJSON) fed to a single-value decoder; whitespace is fine, extra tokens are not.
Common situations: NDJSON logs streamed into Json.decodeValue instead of a line-by-line parser; a producer accidentally emitting the same object twice; concatenating buffered HTTP chunks that each hold a JSON document.
Related errors
- Failed to decode:
- Failed to decode:
- Failed to decode:${e.getMessage()}
- Mapping ${toValueType.getName()} is not available without J
- Failed to decode:
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/3d9d77145cfe40e2.
Report an issue: GitHub.