eclipse-vertx/vert.x · error · DecodeException
Unexpected trailing token
Error message
Unexpected trailing token
What it means
After Jackson reads the requested value, fromParser checks for another token; if the input contains extra non-whitespace content after the first value it throws DecodeException 'Unexpected trailing token'. Vert.x decodes exactly one JSON value per call.
Source
Thrown at vertx-core/src/main/java/io/vertx/core/json/jackson/DatabindCodec.java:135
return DatabindCodec.mapper.getFactory().createParser(str);
} catch (IOException e) {
throw new DecodeException("Failed to decode:" + e.getMessage(), e);
}
}
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
- Decode one value at a time; split NDJSON by '\n' and decode each line.
- Trim the payload and inspect the tail for extra objects/values.
- If multiple values are expected, use JacksonParser streaming manually or a JSON-lines parser.
- Fix the producer to send exactly one JSON document per message.
Example fix
// before
Json.decodeValue(line1 + line2, Config.class); // trailing token
// after
for (String line : payload.split("\n")) {
Config c = Json.decodeValue(line, Config.class);
} Defensive patterns
Strategy: validation
Validate before calling
String t = raw.trim();
int end = indexOfMatchingValue(t); // or simply: assert exactly one top-level value
if (countTopLevelValues(t) > 1) throw new IllegalStateException("payload contains multiple JSON values"); Type guard
static boolean isSingleJsonValue(String s) {
try {
JsonParser p = new ObjectMapper().getFactory().createParser(s);
p.nextToken();
boolean single = p.nextToken() == null;
p.close();
return single;
} catch (Exception e) { return false; }
} Try / catch
try {
Config c = Json.decodeValue(raw, Config.class);
} catch (DecodeException e) {
if ("Unexpected trailing token".equals(e.getMessage())) {
// split NDJSON or fix producer framing
}
} Prevention
- Split newline-delimited JSON before decoding each line.
- Never concatenate messages/frames into one buffer prior to decoding.
- Trim and inspect payload tails for stray characters.
When it happens
Trigger: Json.decodeValue('{"a":1} {"b":2}') — two JSON objects concatenated; newline-delimited JSON fed as a whole; logs/concatenated payloads with a stray second value; invisible trailing characters that Jackson still tokenizes.
Common situations: NDJSON streams consumed without splitting on newlines; accumulating multiple frames into one buffer before decoding; copy-paste of several JSON documents into one config file.
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
- Invalid JSON array: ${json}
- Invalid JSON array: ${buf}
- Invalid JSON object: ${json}
- Invalid JSON object: ${buf}
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/c6b906506038e9e3.
Report an issue: GitHub.