{"id":"c0f7942c2f2e78b8","repo":"gofiber/fiber","slug":"sse-write-event-w","errorCode":null,"errorMessage":"sse: write event: %w","messagePattern":"sse: write event: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"middleware/sse/event.go","lineNumber":67,"sourceCode":"\t}\n\tif event.Name != \"\" {\n\t\tname, err := sanitizeField(event.Name)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"sse: invalid event: %w\", err)\n\t\t}\n\t\tif name != \"\" {\n\t\t\tappendField(&frame, \"event\", name)\n\t\t}\n\t}\n\tif event.Retry > 0 {\n\t\tappendField(&frame, \"retry\", utils.FormatInt(event.Retry.Milliseconds()))\n\t}\n\tif data.hasData {\n\t\tappendData(&frame, data.data)\n\t}\n\tframe.WriteByte('\\n') //nolint:errcheck // bytes.Buffer writes never fail.\n\tif _, err := w.Write(frame.Bytes()); err != nil {\n\t\treturn fmt.Errorf(\"sse: write event: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc writeComment(w *bufio.Writer, comment string) error {\n\tcomment = sanitizeComment(comment)\n\tif comment == \"\" {\n\t\tif _, err := w.WriteString(\":\\n\\n\"); err != nil {\n\t\t\treturn fmt.Errorf(\"sse: write heartbeat: %w\", err)\n\t\t}\n\t\treturn nil\n\t}\n\tfor line := range strings.SplitSeq(comment, \"\\n\") {\n\t\tif _, err := fmt.Fprintf(w, \": %s\\n\", line); err != nil {\n\t\t\treturn fmt.Errorf(\"sse: write comment: %w\", err)\n\t\t}\n\t}\n\tif _, err := w.WriteString(\"\\n\"); err != nil {","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/middleware/sse/event.go#L49-L85","documentation":"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.","triggerScenarios":"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.","commonSituations":"Long-lived SSE connections where clients leave; proxies (nginx/Cloudflare) with aggressive idle timeouts; flaky mobile networks.","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."],"exampleFix":"// before\nfor { stream.Event(ev); time.Sleep(...) } // ignores write error\n\n// after\nfor {\n    select {\n    case <-stream.Done():\n        return // client gone\n    case ev := <-ch:\n        if err := stream.Event(ev); err != nil {\n            return // stop on write failure\n        }\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := stream.Event(ev); err != nil {\n    // Write failed -> client is gone. Stop the loop cleanly.\n    return\n}","preventionTips":["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."],"tags":["sse","network","disconnect","fiber"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}