gofiber/fiber · error

format handler is nil for media type

Error message

format handler is nil for media type %q at index %d

What it means

Thrown by DefaultRes.Format before any content negotiation begins, when one of the supplied ResFmt values has a nil Handler. Format validates every handler up front so that negotiation never selects a handler it cannot call. The message names the offending MediaType and the index in the handlers slice, making it a programmer-error guard, not a runtime/network condition.

Solutions

  1. Ensure every ResFmt passed to Format has a non-nil Handler.
  2. Construct ResFmt values through a helper that requires the handler, so it cannot be omitted.
  3. Add a unit test that asserts all handlers in the slice are non-nil before calling Format.

Example fix

// before
c.Format(
    fiber.ResFmt{MediaType: "application/json"}, // Handler missing
    fiber.ResFmt{MediaType: "text/html", Handler: htmlHandler},
)
// -> format handler is nil for media type "application/json" at index 0

// after
c.Format(
    fiber.ResFmt{MediaType: "application/json", Handler: jsonHandler},
    fiber.ResFmt{MediaType: "text/html", Handler: htmlHandler},
)
Defensive patterns

Strategy: validation

Validate before calling

// Validate the handlers slice before calling Format.
func validateFormats(handlers []fiber.ResFmt) error {
    for i, h := range handlers {
        if h.Handler == nil {
            return fmt.Errorf("handler nil at index %d (%q)", i, h.MediaType)
        }
    }
    return nil
}
if err := validateFormats(handlers); err != nil { return err }
c.Format(handlers...)

Type guard

func allFormatHandlersSet(handlers []fiber.ResFmt) bool {
    for _, h := range handlers {
        if h.Handler == nil { return false }
    }
    return true
}

Try / catch

// Use a constructor that makes a nil Handler impossible to express.
func fmtJSON(h fiber.Handler) fiber.ResFmt { return fiber.ResFmt{MediaType: "application/json", Handler: h} }
c.Format(fmtJSON(jsonHandler), fmtHTML(htmlHandler))

Prevention

When it happens

Trigger: Calling c.Format(...) with a ResFmt literal whose Handler field was omitted (left nil), e.g. ResFmt{MediaType: "application/json"} with no Handler function attached. Often a copy-paste or partial-construction mistake.

Common situations: Building the handlers slice conditionally and forgetting to set Handler on one branch; refactoring that splits MediaType and Handler assignment and drops one; a typo omitting the Handler: key in the struct literal.

Related errors


AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11). Data as JSON: /api/errors/f245c67362758a8b. Report an issue: GitHub.

Appendix: source

Thrown at res.go:441

// formatDefaultMediaType is the sentinel MediaType marking a Format handler as
// the fallback. It is not a media type and is never emitted as a Content-Type.
const formatDefaultMediaType = "default"

// 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 != formatDefaultMediaType {
				r.c.fasthttp.Response.Header.SetContentType(h.MediaType)
				return h.Handler(r.c)

View on GitHub (pinned to a105acad6c)