gofiber/fiber · error
sse: Handler must not be nil
Error message
sse: Handler must not be nil
What it means
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".
Source
Thrown at middleware/sse/sse.go:27
import (
"bufio"
"context"
"errors"
"fmt"
"sync"
"time"
"github.com/gofiber/fiber/v3"
"github.com/gofiber/utils/v2"
)
var errStreamClosed = errors.New("sse: stream closed")
// New creates a new SSE handler.
func New(config ...Config) fiber.Handler {
cfg := configDefault(config...)
if cfg.Handler == nil {
panic("sse: Handler must not be nil")
}
return func(c fiber.Ctx) error {
c.Set(fiber.HeaderContentType, fiber.MIMETextEventStream)
c.Set(fiber.HeaderCacheControl, "no-cache")
c.Set(fiber.HeaderConnection, "keep-alive")
c.Set("X-Accel-Buffering", "no")
streamContext := c.Context()
lastEventID := c.Get(fiber.HeaderLastEventID)
c.Abandon()
return c.SendStreamWriter(func(w *bufio.Writer) {
stream := newStream(streamContext, w, lastEventID, c.App().Config().JSONEncoder)
var streamErr error
defer func() {
if cfg.OnClose != nil {View on GitHub (pinned to 9a4c7e57fe)
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.
Example fix
// before
app.Get("/events", sse.New())
// after
app.Get("/events", sse.New(sse.Config{
Handler: func(c fiber.Ctx, stream *sse.Stream) error {
return stream.Event(sse.Event{Event: "ping", Data: "hello"})
},
})) Defensive patterns
Strategy: validation
Validate before calling
if cfg.Handler == nil {
log.Fatal("sse: Config.Handler must not be nil")
}
app.Get("/events", sse.New(cfg)) Type guard
func hasSSEHandler(cfg sse.Config) bool {
return cfg.Handler != nil
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- runtime.Goexit() called in handler or server panic
- favicon: file size exceeds max bytes %d
- sse: handler panic: %v
- route handler 'fn' cannot be nil
- fiber: Config.RegexHandler return type must support MatchStr
AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04).
Data as JSON: /data/errors/61807293d696957f.json.
Report an issue: GitHub.