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
- Treat write errors as stream termination: stop your handler loop and return.
- Watch stream.Context().Done()/stream.Done() and stop writing when the stream is closed.
- 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
- Always select on stream.Done()/Context().Done() in your send loop.
- Log write errors at debug, not error, level - client disconnects are normal in SSE.
- Set proxy idle timeout > your heartbeat interval.
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
- sse: write heartbeat: %w
- sse: write comment: %w
- sse: finish comment: %w
- sse: write retry: %w
- sse: stream closed
AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04).
Data as JSON: /data/errors/c0f7942c2f2e78b8.json.
Report an issue: GitHub.