Skip to content

Potential regression in charset encoding for Content-Type header #35087

Closed as not planned
@joshdcu

Description

@joshdcu

Note: This issue was originally posted as a Spring Boot issue (spring-boot#46036), but I was informed by a Spring member that the issue was with the Spring Framework and to post the issue here.

Description

Spring version: 6.2.4
Spring Boot version: 3.4.4
Java version: 17
Maven version: 3.9.0

I have a Spring Boot app that:

  1. extends the OncePerRequestFilter to add headers, namely Content-Type and X-Content-Type-Options to every response.
  2. extends the ResponseEntityExceptionHandler to enable custom exception handling for the IllegalArgumentException.
  3. uses Jetty instead of Tomcat.

When I upgraded from Spring 6.2.3 (Spring Boot 3.4.3) to Spring 6.2.4 (Spring Boot 3.4.4), I observed a null value for the charset encoding in the Content-Type response header when I try to access an endpoint/resource that doesn't exist. For the previous version 6.2.3, there was no charset in the first place. null is not recognized as a legal charset so a different Spring Boot REST client that calls this app fails with:

Caused by: org.springframework.util.InvalidMimeTypeException: Invalid mime type "application/problem+json;charset=null": unsupported charset 'null' 

Reproduction

A minimal application that reproduces this error is attached as a demo.zip file with this issue: demo.zip
Download it, extract it to your local machine, build the app (mvn -DskipTests clean package) and run it (java -jar target\demo-0.0.1-SNAPSHOT.jar)...

With Spring 6.2.4:

>curl -v localhost:8080/repro * Uses proxy env variable no_proxy == '127.0.0.1,localhost' * Host localhost:8080 was resolved. * IPv6: ::1 * IPv4: 127.0.0.1 * Trying [::1]:8080... * Connected to localhost (::1) port 8080 > GET /repro HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/8.9.1 > Accept: */* > * Request completely sent off < HTTP/1.1 404 Not Found < Date: Thu, 19 Jun 2025 18:51:06 GMT < X-Content-Type-Options: nosniff < Vary: Origin < Vary: Access-Control-Request-Method < Vary: Access-Control-Request-Headers < Content-Type: application/problem+json;charset=null < Transfer-Encoding: chunked < {"type":"about:blank","title":"Not Found","status":404,"detail":"No static resource repro.","instance":"/repro"}* Connection #0 to host localhost left intact 

With Spring 6.2.3:

>curl -v localhost:8080/repro * Uses proxy env variable no_proxy == '127.0.0.1,localhost' * Host localhost:8080 was resolved. * IPv6: ::1 * IPv4: 127.0.0.1 * Trying [::1]:8080... * Connected to localhost (::1) port 8080 > GET /repro HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/8.9.1 > Accept: */* > * Request completely sent off < HTTP/1.1 404 Not Found < Date: Thu, 19 Jun 2025 18:52:40 GMT < X-Content-Type-Options: nosniff < Content-Type: application/json < Vary: Origin < Vary: Access-Control-Request-Method < Vary: Access-Control-Request-Headers < Transfer-Encoding: chunked < {"type":"about:blank","title":"Not Found","status":404,"detail":"No static resource repro.","instance":"/repro"}* Connection #0 to host localhost left intact 

Notes

I tried various combinations to see what caused this behaviour in Spring 6.2.4. Here are my findings:

Server Extends OncePerRequestFilter? Extends ResponseEntityExceptionHandler? Output
Jetty application/json;charset=null
application/json
application/problem+json
application/json
Tomcat application/json

✔: this class is present in the Spring Boot app
❌: this class is not present in the Spring Boot app
➖: doesn't matter whether or not this class is present in the Spring Boot app

Metadata

Metadata

Assignees

Labels

for: external-projectNeeds a fix in external projectin: webIssues in web modules (web, webmvc, webflux, websocket)status: invalidAn issue that we don't feel is valid

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions