hs-web/hsweb-framework · error · DecodingException
JSON decoding error
Error message
JSON decoding error: ${originalMessage} What it means
Jackson2Tokenizer.tokenize() wraps Jackson's JsonProcessingException into Spring's DecodingException with the original parser message, signalling malformed JSON input while streaming-decoding a byte Flux.
Solutions
- Validate/fix the JSON payload sent by the client
- Ensure Content-Type is application/json and encoding is UTF-8
- Log the full DecodingException cause for the exact parse position
- Test the payload with a strict JSON parser to locate the syntax error
Example fix
// before
curl -X POST -d 'name=abc' /api/items
// after
curl -X POST -H 'Content-Type: application/json' -d '{"name":"abc"}' /api/items Defensive patterns
Strategy: try-catch
Validate before calling
try (JsonParser p = new JsonFactory().createParser(bytes)) { while (p.nextToken() != null) {} } catch (JsonProcessingException e) { /* invalid */ } Type guard
static boolean isValidJson(byte[] bytes) {
try { new JsonFactory().createParser(bytes).readValueAsTree(); return true; }
catch (Exception e) { return false; }
} Try / catch
try {
return tokenizer.tokenize(buffer);
} catch (DecodingException e) {
log.warn("malformed JSON: {}", e.getOriginalMessage());
return Mono.error(ResponseStatusException(HttpStatus.BAD_REQUEST, "Malformed JSON", e));
} Prevention
- Send valid UTF-8 JSON with Content-Type application/json
- Validate payloads client-side before sending
- Map DecodingException to HTTP 400 in reactive handlers
- Test with strict JSON validators in CI
When it happens
Trigger: Feeding invalid JSON bytes (syntax errors, truncated stream, wrong encoding) into the tokenizer's input feeder; parseTokenBufferFlux encounters a token Jackson cannot parse.
Common situations: Client sends malformed request bodies to reactive endpoints expecting JSON; truncated upload; charset mismatch (UTF-8 BOM or invalid bytes); sending form-encoded data to a JSON decoder.
Related errors
AI-assisted analysis of hs-web/hsweb-framework@b2cfc85a57 (2026-09-13).
Data as JSON: /api/errors/81668785318309bd.
Report an issue: GitHub.
Appendix: source
Thrown at hsweb-starter/src/main/java/org/hswebframework/web/starter/jackson/Jackson2Tokenizer.java:89
this.parser = parser;
this.deserializationContext = deserializationContext;
this.tokenizeArrayElements = tokenizeArrayElements;
this.tokenBuffer = new TokenBuffer(parser, deserializationContext);
this.inputFeeder = (ByteArrayFeeder) this.parser.getNonBlockingInputFeeder();
}
private List<TokenBuffer> tokenize(DataBuffer dataBuffer) {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
DataBufferUtils.release(dataBuffer);
try {
this.inputFeeder.feedInput(bytes, 0, bytes.length);
return parseTokenBufferFlux();
}
catch (JsonProcessingException ex) {
throw new DecodingException("JSON decoding error: " + ex.getOriginalMessage(), ex);
}
catch (IOException ex) {
throw Exceptions.propagate(ex);
}
}
private Flux<TokenBuffer> endOfInput() {
return Flux.defer(() -> {
this.inputFeeder.endOfInput();
try {
return Flux.fromIterable(parseTokenBufferFlux());
}
catch (JsonProcessingException ex) {
throw new DecodingException("JSON decoding error: " + ex.getOriginalMessage(), ex);
}
catch (IOException ex) {
throw Exceptions.propagate(ex);
}View on GitHub (pinned to b2cfc85a57)