iflytek/astron-agent · warning · HttpMessageNotReadableException
BAD_REQUEST
BAD_REQUEST
Error message
HTTP message not readable exception: {} What it means
Spring MVC throws HttpMessageNotReadableException when the request body cannot be deserialized into the @RequestBody target type. The handler returns HTTP 400 with BAD_REQUEST code and message 'parameter.illegal'. Commonly caused by malformed JSON or JSON that does not match the target DTO.
Solutions
- Check e.getMessage() in the server log for the Jackson offset message; fix the JSON at the indicated character/line.
- Set the request header Content-Type: application/json on POST/PUT calls with a body.
- Validate the payload against the DTO field names and types; align client serialization with the Java class.
- Ensure the body is non-empty and valid JSON (use a JSON linter or JSON.stringify on the client).
- If using a custom Jackson ObjectMapper/enum deserialization, verify the sent enum values are accepted.
Example fix
// before
fetch('/api/agent', { method: 'POST', body: JSON.stringify(data) }) // no content-type -> not readable
// after
fetch('/api/agent', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }) Defensive patterns
Strategy: validation
Validate before calling
// client-side validation before sending a JSON body
const body = JSON.stringify(payload); // throws SyntaxError on circular refs handled below
function assertSerializable(o) { JSON.stringify(o); return o; }
const safePayload = assertSerializable(payload); Type guard
function isValidJson(text) {
try { const v = JSON.parse(text); return v !== undefined && v !== null; } catch { return false; }
} Try / catch
try {
const res = await api.post('/api/agent', payload, { headers: { 'Content-Type': 'application/json' } });
} catch (e) {
if (e.response?.status === 400 && e.response?.data?.message === 'parameter.illegal') {
console.error('Request body is not readable JSON / does not match DTO');
} else throw e;
} Prevention
- Always set Content-Type: application/json for JSON bodies.
- Validate payloads against the DTO schema (zod/ajv + generated schema) before sending.
- Never send undefined or empty bodies to @RequestBody endpoints.
- Mirror enum/field names exactly between client and Java DTO; regenerate types when the backend changes.
When it happens
Trigger: POST/PUT with @RequestBody where the body is invalid JSON, empty, wrong content type, or fields have incompatible types (e.g. string where an int/enum is expected).
Common situations: Client forgets Content-Type: application/json; sending form-encoded data to a JSON endpoint; JSON field names don't match the DTO; sending 'null'/'undefined' as body; special characters or BOM breaking the JSON parser.
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
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/dfd3e84cf091e7b8.
Report an issue: GitHub.
Appendix: source
Thrown at console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/config/exception/handler/GlobalExceptionHandler.java:91
String messageCode = "parameter.error";
log.warn("Parameter type mismatch exception: {}", messageCode, e);
return ApiResult.error(ResponseEnum.PARAMETER_ERROR.getCode(), messageCode);
}
/** Handle missing request parameter exceptions */
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ApiResult<Void> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
String messageCode = "parameter.missing";
log.warn("Missing request parameter exception: {}", messageCode);
return ApiResult.error(ResponseEnum.PARAMETER_ERROR.getCode(), messageCode);
}
/** Handle HTTP message not readable exceptions */
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ApiResult<Void> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
log.warn("HTTP message not readable exception: {}", e.getMessage(), e);
return ApiResult.error(ResponseEnum.BAD_REQUEST.getCode(), "parameter.illegal");
}
/** Handle HTTP request method not supported exceptions */
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
public ApiResult<Void> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
String messageCode = "http.method.not.supported";
log.warn("HTTP request method not supported exception: {}", messageCode, e);
return ApiResult.error(ResponseEnum.METHOD_NOT_ALLOWED.getCode(), messageCode);
}
/** Handle handler not found exceptions */
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ApiResult<Void> handleNoHandlerFoundException(NoHandlerFoundException e) {
String messageCode = "http.url.not.found";
log.warn("Handler not found exception: {}", messageCode, e);View on GitHub (pinned to 5e758547a8)