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

  1. Provide a non-nil fiber.Handler for every ResFmt.
  2. 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

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


AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04). Data as JSON: /data/errors/f245c67362758a8b.json. Report an issue: GitHub.