eclipse-vertx/vert.x · error · DecodeException
Unexpected trailing token
Error message
Unexpected trailing token
What it means
JacksonCodec.fromParser consumes a JsonParser expecting exactly one JSON value; after decoding, any leftover tokens (unless a deferred 'remaining' state was intentionally kept) mean the input contains more content than a single value. The codec throws DecodeException("Unexpected trailing token") in that case. This guards against inputs like '{...} {...}' or a value followed by garbage.
Source
Thrown at vertx-core/src/main/java21/io/vertx/core/json/jackson/v3/JacksonCodec.java:240
private static JsonGenerator createGenerator(OutputStream out, boolean pretty) {
return factory.createGenerator(owc(pretty), out);
}
public static <T> T fromParser(JsonParser parser, Class<T> type) throws DecodeException {
Object res;
JsonToken remaining;
try {
parser.nextToken();
res = parseValue(parser);
remaining = parser.nextToken();
} catch (JacksonException | IOException e) {
throw new DecodeException(e.getMessage(), e);
} finally {
close(parser);
}
if (remaining != null) {
throw new DecodeException("Unexpected trailing token");
}
return cast(res, type);
}
private static Object parseValue(JsonParser parser) throws IOException, DecodeException {
switch (parser.currentTokenId()) {
case JsonTokenId.ID_START_OBJECT:
return parseObject(parser);
case JsonTokenId.ID_START_ARRAY:
return parseArray(parser);
case JsonTokenId.ID_STRING:
return parser.getString();
case JsonTokenId.ID_NUMBER_FLOAT:
case JsonTokenId.ID_NUMBER_INT:
return parser.getNumberValue();
case JsonTokenId.ID_TRUE:
return Boolean.TRUE;
case JsonTokenId.ID_FALSE:View on GitHub (pinned to fb308bd8c3)
Solutions
- Ensure the input contains exactly one JSON value; split NDJSON input into lines and decode each line separately
- Strip or trim extraneous characters from the payload before decoding
- If multiple concatenated values are intentional, use a streaming/token-by-token parse loop instead of fromParser
Example fix
// before
String ndjson = "{\"a\":1}\n{\"a\":2}";
Object o = Json.decodeValue(ndjson); // DecodeException: Unexpected trailing token
// after
List<Object> all = new ArrayList<>();
for (String line : ndjson.split("\n")) all.add(Json.decodeValue(line)); Defensive patterns
Strategy: try-catch
Validate before calling
// single-value check before decode
String t = input.trim();
if (!(t.startsWith("{") || t.startsWith("["))) throw new IllegalArgumentException("not JSON");
// for suspected NDJSON, ensure exactly one line: input.indexOf('\n') == -1 Try / catch
try {
Object o = Json.decodeValue(buffer);
} catch (DecodeException e) {
if (e.getMessage().contains("Unexpected trailing token")) {
// split input into multiple documents and decode each
}
} Prevention
- Split JSON Lines/NDJSON into per-line decodes instead of decoding the whole stream
- Trim and sanity-check payloads received from external producers
- Log the raw payload when this exception occurs to spot concatenation bugs
When it happens
Trigger: Calling JacksonCodec.fromParser (directly or via Json.decodeValue with an ObjectMapper readTree-style flow) on input containing more than one top-level JSON value, e.g. JSON Lines fed to a single-value decoder, concatenated JSON objects, or a JSON value followed by extra characters.
Common situations: NDJSON/log-line files parsed as one JSON document; two JSON payloads accidentally concatenated by a producer; trailing whitespace is fine but an accidental second token (comma-separated records) triggers this.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- Unexpected trailing token
- Expecting the current parser token to be the start of an obj
- Expecting the current parser token to be the start of an arr
- Failed to decode
- Unexpected trailing token
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/968cd7ace1c30c1f.
Report an issue: GitHub.