eclipse-vertx/vert.x · error · DecodeException

Failed to decode:${e.getMessage()}

Error message

Failed to decode:${e.getMessage()}

What it means

DatabindCodec.fromStream wraps any IOException raised while creating or reading a Jackson JsonParser from an InputStream into a DecodeException 'Failed to decode:...'. It signals the input stream did not yield parseable JSON.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/json/jackson/DatabindCodec.java:103

  }

  @Override
  public <T> T fromBuffer(Buffer buf, Class<T> clazz) throws DecodeException {
    return fromParser(createParser(buf), clazz);
  }

  public <T> T fromBuffer(Buffer buf, TypeReference<T> typeRef) throws DecodeException {
    return fromParser(createParser(buf), typeRef);
  }

  @Override
  public <T> T fromStream(InputStream in, Class<T> clazz) throws DecodeException {
    try {
      JsonParser parser = mapper.getFactory().createParser(in);
      parser.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE);
      return fromParser(parser, clazz);
    } catch (IOException e) {
      throw new DecodeException("Failed to decode:" + e.getMessage(), e);
    }
  }

  public static JsonParser createParser(BufferInternal buf) {
    try {
      return DatabindCodec.mapper.getFactory().createParser((InputStream) new ByteBufInputStream(buf.getByteBuf()));
    } catch (IOException e) {
      throw new DecodeException("Failed to decode:" + e.getMessage(), e);
    }
  }

  public static JsonParser createParser(String str) {
    try {
      return DatabindCodec.mapper.getFactory().createParser(str);
    } catch (IOException e) {
      throw new DecodeException("Failed to decode:" + e.getMessage(), e);
    }
  }

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Check getCause() for the underlying IOException message (it names the real problem).
  2. Verify the stream is open and positioned at the start (re-open the resource rather than reusing a consumed stream).
  3. Validate the JSON is well-formed (e.g. dump the bytes first: IOUtils.toString).
  4. Ensure the stream charset is UTF-8 or another JSON-compatible encoding.

Example fix

// before
InputStream in = socket.getInputStream();
Json.decodeValue(in, Config.class); // DecodeException on truncated data
// after
String text = in.readAllBytes() ... validate;
if (!text.trim().isEmpty()) {
  Config c = Json.decodeValue(Buffer.buffer(text), Config.class);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (in == null) throw new IllegalArgumentException("input stream is null");
if (in.available() == 0 && expectsData) throw new IllegalStateException("input stream is empty");

Type guard

static boolean hasReadableData(InputStream in) throws IOException {
  return in != null && in.read() != -1; // mark/reset to rewind if supported
}

Try / catch

try (InputStream in = openStream()) {
  return Json.decodeValue(in, Config.class);
} catch (DecodeException e) {
  throw new ConfigException("Cannot parse config: " + e.getCause().getMessage(), e);
}

Prevention

When it happens

Trigger: Json.decodeValue(InputStream) / DatabindCodec.fromStream(clazz) with an empty stream, already-closed stream, malformed JSON, an invalid charset, or an IO error mid-read (network drop, premature EOF).

Common situations: Reading a config resource that does not exist on the classpath (stream is empty/null content); passing a response body stream that was already consumed; feeding truncated JSON from a socket.

Understand the failure class

Related errors


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/e9e680ebc9716ec6. Report an issue: GitHub.