hs-web/hsweb-framework · warning · UnsupportedMediaTypeStatusException

unsupported_media_type

unsupported_media_type

Error message

error.unsupported_media_type

What it means

WebFlux's UnsupportedMediaTypeStatusException is translated to HTTP 415 with code unsupported_media_type, the localized 'error.unsupported_media_type' message, and the list of supported media types attached to the response result. It means the client sent a body with a Content-Type the endpoint cannot consume.

Solutions

  1. Set the request Content-Type header to a type the endpoint supports (see supportedMediaTypes in the response body).
  2. If sending JSON, use application/json and serialize the body correctly.
  3. If the endpoint should accept another type, register a HttpMessageReader/decoder for that media type in the server codec configuration.
  4. Check proxies/gateways for headers stripped or rewritten.

Example fix

// before
fetch('/api/user', {method:'POST', body: JSON.stringify(u)}) // no Content-Type
// after
fetch('/api/user', {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(u)})
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED = ['application/json'];
if (!SUPPORTED.includes(headers['Content-Type'])) {
  throw new Error(`Unsupported Content-Type: ${headers['Content-Type']}; use application/json`);
}

Try / catch

try {
  return await client.post(url, body, { headers: { 'Content-Type': 'application/json' } });
} catch (e) {
  if (e.response && e.response.status === 415) {
    console.warn('415: use one of', e.response.data.result);
  }
  throw e;
}

Prevention

When it happens

Trigger: POST/PUT with Content-Type like text/plain or application/x-www-form-urlencoded to an endpoint that decodes @RequestBody as JSON/other; missing Content-Type header where none can be inferred; Accept on the client forcing an unsupported writer during encoding.

Common situations: Older HTTP clients or curl defaults (application/x-www-form-urlencoded) posting JSON; misconfigured gateway rewriting Content-Type; API consumers ignoring the documented media type.

Related errors


AI-assisted analysis of hs-web/hsweb-framework@b2cfc85a57 (2026-09-13). Data as JSON: /api/errors/8e8ed7893117ef3d. Report an issue: GitHub.

Appendix: source

Thrown at hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonErrorControllerAdvice.java:235

        return LocaleUtils
            .resolveThrowable(e, (err, msg) -> {
                log.warn(msg, e);
                return ResponseMessage.error(400, CodeConstants.Error.illegal_argument, msg);
            });
    }

    @ExceptionHandler
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Mono<ResponseMessage<Object>> handleException(AuthenticationException e) {
        return LocaleUtils
            .resolveThrowable(e, (err, msg) -> ResponseMessage.error(400, err.getCode(), msg));
    }

    @ExceptionHandler
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    public Mono<ResponseMessage<Object>> handleException(UnsupportedMediaTypeStatusException e) {
        log.warn(e.getLocalizedMessage(), e);

        return LocaleUtils
            .resolveMessageReactive("error.unsupported_media_type")
            .map(msg -> ResponseMessage
                .error(415, "unsupported_media_type", msg)
                .result(e.getSupportedMediaTypes()));
    }

    @ExceptionHandler
    @ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
    public Mono<ResponseMessage<Object>> handleException(NotAcceptableStatusException e) {
        log.warn(e.getLocalizedMessage(), e);

        return LocaleUtils
            .resolveMessageReactive("error.not_acceptable_media_type")
            .map(msg -> ResponseMessage
                .error(406, "not_acceptable_media_type", msg)
                .result(e.getSupportedMediaTypes()));

View on GitHub (pinned to b2cfc85a57)