Cookies management by TermsFeed Cookie Consent

🪠 Handle 'broken pipe' error in Go

Last updated:
http errors

The broken pipe is a TCP/IP error occurring when you write to a stream where the other end (the peer) has closed the underlying connection. The first write to the closed connection causes the peer to reply with an RST packet indicating that the connection should be terminated immediately. The second write to the socket that has already received the RST causes the broken pipe error. To detect the broken pipe in Go, check if the error returned by the peer is equal to syscall.EPIPE. Usually, this error can be seen when the server crashes while the client is sending data to it.

Reproduce the broken pipe error

In the following example, we reproduce the broken pipe error by creating a server and client that do the following:

The server receives the first client byte and closes the connection. The next byte of the client sent to the closed connection causes the server to reply with an RST packet. The socket that received the RST will return the broken pipe error when more bytes are sent to it. This is what happens when the client sends the last byte to the server.

package main

import (
    "errors"
    "log"
    "net"
    "os"
    "syscall"
    "time"
)

func server() {
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        log.Fatal(err)
    }

    defer listener.Close()

    conn, err := listener.Accept()
    if err != nil {
        log.Fatal("server", err)
        os.Exit(1)
    }
    data := make([]byte, 1)
    if _, err := conn.Read(data); err != nil {
        log.Fatal("server", err)
    }

    conn.Close()
}

func client() {
    conn, err := net.Dial("tcp", "localhost:8080")
    if err != nil {
        log.Fatal("client", err)
    }

    // write to make the connection closed on the server side
    if _, err := conn.Write([]byte("a")); err != nil {
        log.Printf("client: %v", err)
    }

    time.Sleep(1 * time.Second)

    // write to generate an RST packet
    if _, err := conn.Write([]byte("b")); err != nil {
        log.Printf("client: %v", err)
    }

    time.Sleep(1 * time.Second)

    // write to generate the broken pipe error
    if _, err := conn.Write([]byte("c")); err != nil {
        log.Printf("client: %v", err)
        if errors.Is(err, syscall.EPIPE) {
            log.Print("This is broken pipe error")
        }
    }
}

func main() {
    go server()

    time.Sleep(3 * time.Second) // wait for server to run

    client()
}

Output:

2021/10/21 19:10:01 client: write tcp 127.0.0.1:50389->127.0.0.1:8080: write: broken pipe
2021/10/21 19:10:01 This is broken pipe error

Handle the broken pipe error

To handle the broken pipe, you need to check if the error returned from the other end of the connection is an instance of syscall.EPIPE. In the example above, we perform this check using the errors.Is() function and print the message "This is broken pipe error" if it occurs. The broken pipe can be seen on either the client or server side, depending on which one is trying to write to the closed connection. Typically there is no need to handle it in any special way since it is normal that a connection may be interrupted by either side of the communication. For example, you can ignore the error, log it or reconnect when it occurs.

Difference between broken pipe and connection reset by peer

Usually, you get the broken pipe error when you write to the connection after the RST is sent, and when you read from the connection after the RST instead, you get the connection reset by peer error. Check our article about connection reset by peer error to better understand the difference between these two errors.


Thank you for being on our site 😊. If you like our tutorials and examples, please consider supporting us with a cup of coffee and we'll turn it into more great Go examples.

Have a great day!

Buy Me A Coffee

🔌 Handle 'connection reset by peer' error in Go

Learn what it means and how to detect the ‘connection reset by peer’ error
http errors

📡 Handle Context Deadline Exceeded error in Go

Learn how to check if a HTTP client returns a request timeout error
http errors

📔 Convert a struct to io.Reader in Go

Learn how to convert a struct to io.Reader and send it as an HTTP POST request body
introduction http