Skip to content

When connection to client is lost while writing JSON, it should not be logged as warningΒ #37151

Closed

Description

@michaldo

Prior discussion in #34481 (comment).

There is a class which identifies when client breaks connection: org.springframework.web.util.DisconnectedClientHelper
Unfortunately, when JSON is being written to output stream, org.springframework.http.converter.AbstractJacksonHttpMessageConverter#writeInternal identifies it as HttpMessageNotWritableException
Both identification collides and finally application produces output like:

WARN .w.s.m.s.DefaultHandlerExceptionResolver : Ignoring exception, response committed already: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: ServletOutputStream failed to write: java.io.IOException: Broken pipe

Expected behavior: no warning at all.

Affects: spring-framework 7.0.8

Steps to reproduce:

  1. pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>4.1.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>broken-pipe-demo</groupId>
    <artifactId>broken-pipe-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <java.version>25</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webmvc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-docker-compose</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>eu.rekawek.toxiproxy</groupId>
            <artifactId>toxiproxy-java</artifactId>
            <version>2.1.7</version>
        </dependency>

    </dependencies>
</project>
  1. compose.yaml (prepared for Windows, may need adjustment for Linux)
services:
  toxiproxy:
    image: ghcr.io/shopify/toxiproxy:2.12.0
    container_name: toxiproxy
    ports:
      - "8474:8474"   # Toxiproxy API (for managing proxies and toxics)
      - "8081:8081"   # proxy
    labels:
      org.springframework.boot.ignore: true
  1. application
package brokenpipedemo.brokenpipedemo;

import eu.rekawek.toxiproxy.ToxiproxyClient;
import eu.rekawek.toxiproxy.model.ToxicDirection;
import jakarta.annotation.PostConstruct;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.stream.IntStream;

@SpringBootApplication
@RestController
public class BrokenPipeDemoApplication {

    static void main(String[] args) {
        SpringApplication.run(BrokenPipeDemoApplication.class, args);
    }

    @PostConstruct
    void toxiProxySetup() throws IOException {
        new ToxiproxyClient("localhost", 8474)
                .createProxy("broken-pipe", "0.0.0.0:8081", "host.docker.internal:8080")
                .toxics()
                .resetPeer("immediate", ToxicDirection.DOWNSTREAM, 0);
    }

    @GetMapping
    int[] get() {
        return IntStream.range(0, 100_000).toArray();
    }
}
  1. curl localhost:8080 is ok
  2. curl localhost:8081 triggers warning in application log

Activity

  1. self-assigned this
    on Aug 19, 2026
  2. added
    in: webIssues in web modules (web, webmvc, webflux, websocket)
    on Aug 19, 2026
  3. changed the title [-]When client breaks connection to application, it should not be logged as warning[/-] [+]When connection to client is lost while writing JSON, it should not be logged as warning[/+] on Aug 19, 2026
  4. added this to the 7.0.10 milestone on Aug 19, 2026
  5. rstoyanchev commented on Aug 19, 2026

    @rstoyanchev
    Contributor

    In response to your concerns in #34481 (comment), DefaultHandlerExceptionResolver handles framework exceptions. Many of those are client errors, and from the rest aren't related to I/O.

    HttpMessageNotReadableException and HttpMessageNotWriteableException are the only ones where we use to wrap I/O errors. If we add logic to detect if the cause of those is a lost connection, and avoid logging, that should be sufficient. I don't think it needs anything more than that.

  6. modified the milestones: 7.0.10, 7.1.0-M2 on Aug 24, 2026
  7. Shubh2-0 commented on Aug 25, 2026

    @Shubh2-0

    Makes sense @rstoyanchev. Unwrapping HttpMessageNotWritableException and checking if its underlying cause matches DisconnectedClientHelper.isClientDisconnectedException(...) before logging will keep DefaultHandlerExceptionResolver clean without swallowing actual serialization errors.\n\nI'd be glad to take this up and submit a PR if it's open for contributions.

  8. rstoyanchev commented on Aug 25, 2026

    @rstoyanchev
    Contributor

    It's not open for contribution. There are a few different ways it could be done, and haven't really made up my mind.

  9. michaldo commented on Aug 26, 2026

    @michaldo
    Author

    I would like to add my two cents.
    When one hand takes an exception, looks at the exception and decides: It is HttpMessageNotWritableException and other hand takes HttpMessageNotWritableException, looks inside and decides: it is not HttpMessageNotWritableException, it is ClientDisconnectedException,
    something is wrong

  10. rstoyanchev commented on Aug 27, 2026

    @rstoyanchev
    Contributor

    It's HttpMessageNotWritableException in both cases. A more general exception with different causes.

  11. added a commit that references this issue on Sep 15, 2026
    33988a4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)type: enhancementA general enhancement

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions