gofiber/fiber · error
format handler is nil for media type %q at index %d
Error message
format handler is nil for media type %q at index %d
What it means
Format() validates every ResFmt passed to it and rejects any whose Handler is nil, because invoking a nil Handler would panic. The error names the offending media type and slice index so you can locate the bad entry. This is a programmer error, not a runtime/environment condition.
Source
Thrown at res.go:437
// https://godoc.org/github.com/valyala/fasthttp#Response
func (r *DefaultRes) Response() *fasthttp.Response {
return &r.c.fasthttp.Response
}
// Format performs content-negotiation on the Accept HTTP header.
// It uses Accepts to select a proper format and calls the matching
// user-provided handler function.
// If no accepted format is found, and a format with MediaType "default" is given,
// that default handler is called. If no format is found and no default is given,
// StatusNotAcceptable is sent.
func (r *DefaultRes) Format(handlers ...ResFmt) error {
if len(handlers) == 0 {
return ErrNoHandlers
}
for i, h := range handlers {
if h.Handler == nil {
return fmt.Errorf("format handler is nil for media type %q at index %d", h.MediaType, i)
}
}
r.Vary(HeaderAccept)
// Absent means the combined Accept view (RFC 9110 Section 5.2) is empty:
// no field line, or a single empty one. Checked on the raw lines to skip
// the join allocation that multi-line headers would pay.
accepts := r.c.fasthttp.Request.Header.PeekAll(HeaderAccept)
if len(accepts) == 0 || (len(accepts) == 1 && len(accepts[0]) == 0) {
// Without an Accept header the client accepts any media type
// (RFC 9110 Section 12.5.1), so pick the first non-default handler and
// use its media type. The literal "default" is not a media type and
// must not be emitted as a Content-Type value.
for _, h := range handlers {
if h.MediaType != "default" {
r.c.fasthttp.Response.Header.SetContentType(h.MediaType)
return h.Handler(r.c)View on GitHub (pinned to 9a4c7e57fe)
Solutions
- Provide a non-nil fiber.Handler for every ResFmt.
- Build the slice dynamically and skip/filter entries whose Handler is nil before calling Format.
Example fix
// before
c.Format(
ResFmt{MediaType: "application/json", Handler: jsonHandler},
ResFmt{MediaType: "text/html"}, // Handler missing -> error
)
// after
c.Format(
ResFmt{MediaType: "application/json", Handler: jsonHandler},
ResFmt{MediaType: "text/html", Handler: htmlHandler},
) Defensive patterns
Strategy: validation
Validate before calling
func cleanFmts(fmts []ResFmt) []ResFmt {
out := make([]ResFmt, 0, len(fmts))
for _, f := range fmts {
if f.Handler != nil {
out = append(out, f)
}
}
return out
}
// then: c.Format(cleanFmts(fmts)...) Try / catch
if err := c.Format(fmts...); err != nil {
if strings.Contains(err.Error(), "format handler is nil") {
// programming error: fix the ResFmt slice
panic(err)
}
return err
} Prevention
- Never construct ResFmt without a Handler.
- Filter nil-handler entries when building slices dynamically.
- Add a unit test asserting all format handlers are non-nil.
When it happens
Trigger: Calling c.Format(ResFmt{MediaType: "application/json"}) with the Handler field missing, or building a handlers slice where one branch leaves Handler nil.
Common situations: Conditionally assembling a ResFmt slice and forgetting a branch; copy-paste omission; passing a nil handler variable.
Related errors
- format: at least one handler is required, but none were set
- log: context tag name and function are required
- sse: invalid id: %w
- sse: invalid event: %w
- min constraint requires an argument
AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04).
Data as JSON: /data/errors/f245c67362758a8b.json.
Report an issue: GitHub.