gin-gonic/gin · warning

the accepted formats are not offered by the server

Error message

the accepted formats are not offered by the server

What it means

Returned via c.AbortWithError(http.StatusNotAcceptable, ...) inside Context.Negotiate (context.go:1445) when the client's Accept header does not match any of the offered MIME types. Negotiate first calls NegotiateFormat(offered...); if none match it falls into the default branch and returns 406 Not Acceptable.

Source

Thrown at context.go:1445

	case binding.MIMEYAML, binding.MIMEYAML2:
		data := chooseData(config.YAMLData, config.Data)
		c.YAML(code, data)

	case binding.MIMETOML:
		data := chooseData(config.TOMLData, config.Data)
		c.TOML(code, data)

	case binding.MIMEPROTOBUF:
		data := chooseData(config.PROTOBUFData, config.Data)
		c.ProtoBuf(code, data)

	case binding.MIMEBSON:
		data := chooseData(config.BSONData, config.Data)
		c.BSON(code, data)

	default:
		c.AbortWithError(http.StatusNotAcceptable, errors.New("the accepted formats are not offered by the server")) //nolint: errcheck
	}
}

// NegotiateFormat returns an acceptable Accept format.
func (c *Context) NegotiateFormat(offered ...string) string {
	assert1(len(offered) > 0, "you must provide at least one offer")

	if c.Accepted == nil {
		c.Accepted = parseAccept(c.requestHeader("Accept"))
	}
	if len(c.Accepted) == 0 {
		return offered[0]
	}
	for _, accepted := range c.Accepted {
		for _, offer := range offered {
			// According to RFC 2616 and RFC 2396, non-ASCII characters are not allowed in headers,
			// therefore we can just iterate over the string without casting it into []rune
			i := 0

View on GitHub (pinned to 34dac209ff)

Solutions

  1. Add the requested MIME type to config.Offered (and supply the matching *Data field, e.g. JSONData).
  2. On the client, request a format the server actually offers, or send Accept: */* (NegotiateFormat returns offered[0]).
  3. Provide a fallback handler / default case that renders a generic representation when Accept does not match.

Example fix

// before
c.Negotiate(http.StatusOK, gin.Negotiate{
    Offered:  []string{binding.MIMEJSON},
    JSONData: payload,
})
// client asked for XML -> 406
// after
c.Negotiate(http.StatusOK, gin.Negotiate{
    Offered:  []string{binding.MIMEJSON, binding.MIMEXML},
    JSONData: payload,
    XMLData:  payload,
})
Defensive patterns

Strategy: validation

Validate before calling

offered := []string{binding.MIMEJSON, binding.MIMEXML}
if format := c.NegotiateFormat(offered...); format == "" {
    c.AbortWithStatus(http.StatusNotAcceptable)
    return
}
c.Negotiate(http.StatusOK, gin.Negotiate{Offered: offered, /* ... */})

Prevention

When it happens

Trigger: Client sends Accept: text/xml but the server only offered binding.MIMEJSON; client sends Accept: application/json but Offered only contains MIMEHTML; client sends */* with an empty Offered list (asserts earlier) or a strict, unsupported media type.

Common situations: Forgetting to list a format in Offered; frontend switched Accept header (e.g. to application/msgpack); version skew where a new client asks for a format the old server does not offer.

Related errors


AI-assisted analysis of gin-gonic/gin@34dac209ff (2026-08-04). Data as JSON: /data/errors/631c810497f68487.json. Report an issue: GitHub.