{"record":{"id":"968cd7ace1c30c1f","repo":"eclipse-vertx/vert.x","slug":"unexpected-trailing-token-968cd7","errorCode":null,"errorMessage":"Unexpected trailing token","messagePattern":"Unexpected trailing token","errorType":"exception","errorClass":"DecodeException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java21/io/vertx/core/json/jackson/v3/JacksonCodec.java","lineNumber":240,"sourceCode":"\n  private static JsonGenerator createGenerator(OutputStream out, boolean pretty) {\n    return factory.createGenerator(owc(pretty), out);\n  }\n\n  public static <T> T fromParser(JsonParser parser, Class<T> type) throws DecodeException {\n    Object res;\n    JsonToken remaining;\n    try {\n      parser.nextToken();\n      res = parseValue(parser);\n      remaining = parser.nextToken();\n    } catch (JacksonException | IOException e) {\n      throw new DecodeException(e.getMessage(), e);\n    } finally {\n      close(parser);\n    }\n    if (remaining != null) {\n      throw new DecodeException(\"Unexpected trailing token\");\n    }\n    return cast(res, type);\n  }\n\n  private static Object parseValue(JsonParser parser) throws IOException, DecodeException {\n    switch (parser.currentTokenId()) {\n      case JsonTokenId.ID_START_OBJECT:\n        return parseObject(parser);\n      case JsonTokenId.ID_START_ARRAY:\n        return parseArray(parser);\n      case JsonTokenId.ID_STRING:\n        return parser.getString();\n      case JsonTokenId.ID_NUMBER_FLOAT:\n      case JsonTokenId.ID_NUMBER_INT:\n        return parser.getNumberValue();\n      case JsonTokenId.ID_TRUE:\n        return Boolean.TRUE;\n      case JsonTokenId.ID_FALSE:","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java21/io/vertx/core/json/jackson/v3/JacksonCodec.java#L222-L258","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nString ndjson = \"{\\\"a\\\":1}\\n{\\\"a\\\":2}\";\nObject o = Json.decodeValue(ndjson); // DecodeException: Unexpected trailing token\n// after\nList<Object> all = new ArrayList<>();\nfor (String line : ndjson.split(\"\\n\")) all.add(Json.decodeValue(line));","handlingStrategy":"try-catch","validationCode":"// single-value check before decode\nString t = input.trim();\nif (!(t.startsWith(\"{\") || t.startsWith(\"[\"))) throw new IllegalArgumentException(\"not JSON\");\n// for suspected NDJSON, ensure exactly one line: input.indexOf('\\n') == -1","typeGuard":null,"tryCatchPattern":"try {\n  Object o = Json.decodeValue(buffer);\n} catch (DecodeException e) {\n  if (e.getMessage().contains(\"Unexpected trailing token\")) {\n    // split input into multiple documents and decode each\n  }\n}","preventionTips":["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"],"tags":["java","json","decoding","ndjson"],"backgroundTag":"json-parse-error","analyzedSha":"fb308bd8c3f12c79f4ae89bef67fadf6c80d036e","analyzedAt":"2026-09-06T11:37:12.241Z","contentChangedAt":"2026-09-06T11:37:12.241Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}