gofiber/fiber · info

sse: write event: %w

Error message

sse: write event: %w

What it means

Writing a fully-formed SSE event frame to the HTTP response stream failed at w.Write. In an SSE stream this almost always means the client has disconnected (closed tab, navigated away, network loss) or the connection was reset; fasthttp's writer returns the underlying broken-pipe error.

Source

Thrown at middleware/sse/event.go:67

	}
	if event.Name != "" {
		name, err := sanitizeField(event.Name)
		if err != nil {
			return fmt.Errorf("sse: invalid event: %w", err)
		}
		if name != "" {
			appendField(&frame, "event", name)
		}
	}
	if event.Retry > 0 {
		appendField(&frame, "retry", utils.FormatInt(event.Retry.Milliseconds()))
	}
	if data.hasData {
		appendData(&frame, data.data)
	}
	frame.WriteByte('\n') //nolint:errcheck // bytes.Buffer writes never fail.
	if _, err := w.Write(frame.Bytes()); err != nil {
		return fmt.Errorf("sse: write event: %w", err)
	}
	return nil
}

func writeComment(w *bufio.Writer, comment string) error {
	comment = sanitizeComment(comment)
	if comment == "" {
		if _, err := w.WriteString(":\n\n"); err != nil {
			return fmt.Errorf("sse: write heartbeat: %w", err)
		}
		return nil
	}
	for line := range strings.SplitSeq(comment, "\n") {
		if _, err := fmt.Fprintf(w, ": %s\n", line); err != nil {
			return fmt.Errorf("sse: write comment: %w", err)
		}
	}
	if _, err := w.WriteString("\n"); err != nil {

View on GitHub (pinned to 9a4c7e57fe)

Solutions

  1. Treat write errors as stream termination: stop your handler loop and return.
  2. Watch stream.Context().Done()/stream.Done() and stop writing when the stream is closed.
  3. Tune reverse-proxy idle/read timeouts if disconnects happen before your intended heartbeat interval.

Example fix

// before
for { stream.Event(ev); time.Sleep(...) } // ignores write error

// after
for {
    select {
    case <-stream.Done():
        return // client gone
    case ev := <-ch:
        if err := stream.Event(ev); err != nil {
            return // stop on write failure
        }
    }
}
Defensive patterns

Strategy: try-catch

Try / catch

if err := stream.Event(ev); err != nil {
    // Write failed -> client is gone. Stop the loop cleanly.
    return
}

Prevention

When it happens

Trigger: Calling stream.Event(...) on a stream whose client has gone away, or after a reverse proxy timed out the connection; mobile client switching networks mid-stream.

Common situations: Long-lived SSE connections where clients leave; proxies (nginx/Cloudflare) with aggressive idle timeouts; flaky mobile networks.

Related errors


AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04). Data as JSON: /data/errors/c0f7942c2f2e78b8.json. Report an issue: GitHub.