{"id":"61807293d696957f","repo":"gofiber/fiber","slug":"sse-handler-must-not-be-nil","errorCode":null,"errorMessage":"sse: Handler must not be nil","messagePattern":"sse: Handler must not be nil","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/sse/sse.go","lineNumber":27,"sourceCode":"import (\n\t\"bufio\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/gofiber/fiber/v3\"\n\t\"github.com/gofiber/utils/v2\"\n)\n\nvar errStreamClosed = errors.New(\"sse: stream closed\")\n\n// New creates a new SSE handler.\nfunc New(config ...Config) fiber.Handler {\n\tcfg := configDefault(config...)\n\tif cfg.Handler == nil {\n\t\tpanic(\"sse: Handler must not be nil\")\n\t}\n\n\treturn func(c fiber.Ctx) error {\n\t\tc.Set(fiber.HeaderContentType, fiber.MIMETextEventStream)\n\t\tc.Set(fiber.HeaderCacheControl, \"no-cache\")\n\t\tc.Set(fiber.HeaderConnection, \"keep-alive\")\n\t\tc.Set(\"X-Accel-Buffering\", \"no\")\n\n\t\tstreamContext := c.Context()\n\t\tlastEventID := c.Get(fiber.HeaderLastEventID)\n\n\t\tc.Abandon()\n\n\t\treturn c.SendStreamWriter(func(w *bufio.Writer) {\n\t\t\tstream := newStream(streamContext, w, lastEventID, c.App().Config().JSONEncoder)\n\t\t\tvar streamErr error\n\t\t\tdefer func() {\n\t\t\t\tif cfg.OnClose != nil {","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/middleware/sse/sse.go#L9-L45","documentation":"sse.New constructs a Server-Sent Events handler from a Config, and the Config.Handler (the function that writes events to the stream) is the only required field. If it is nil the middleware has nothing to execute per connection, so sse.New panics with \"sse: Handler must not be nil\".","triggerScenarios":"Calling sse.New() with no config, or with a Config where the Handler field is not set. The default config leaves Handler as nil, so omitting it always triggers this panic.","commonSituations":"Calling sse.New() bare expecting a default behavior. Building Config incrementally and forgetting to assign Handler. Copying an example that omitted the Handler for brevity.","solutions":["Provide a Config with a non-nil Handler: sse.New(sse.Config{Handler: func(c fiber.Ctx, stream *sse.Stream) error {...}}).","Define the handler as a named function and assign it to Handler to keep config readable.","If you only need the streaming plumbing, still supply a minimal handler that drives your event source."],"exampleFix":"// before\napp.Get(\"/events\", sse.New())\n// after\napp.Get(\"/events\", sse.New(sse.Config{\n    Handler: func(c fiber.Ctx, stream *sse.Stream) error {\n        return stream.Event(sse.Event{Event: \"ping\", Data: \"hello\"})\n    },\n}))","handlingStrategy":"validation","validationCode":"if cfg.Handler == nil {\n    log.Fatal(\"sse: Config.Handler must not be nil\")\n}\napp.Get(\"/events\", sse.New(cfg))","typeGuard":"func hasSSEHandler(cfg sse.Config) bool {\n    return cfg.Handler != nil\n}","tryCatchPattern":null,"preventionTips":["Always pass sse.Config with an explicit Handler; never call sse.New() with no arguments.","Define the handler as a named function and assign it to keep config clear."],"tags":["sse","config","handler","panic"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}