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 := 0View on GitHub (pinned to 34dac209ff)
Solutions
- Add the requested MIME type to config.Offered (and supply the matching *Data field, e.g. JSONData).
- On the client, request a format the server actually offers, or send Accept: */* (NegotiateFormat returns offered[0]).
- 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
- Always pass a non-empty Offered list whose entries you can actually render.
- Call NegotiateFormat yourself first and handle the empty case explicitly.
- Document the Accept types your endpoint supports in the route registration / OpenAPI spec.
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
- unknown type
- can not convert to map slices of strings
- can not convert to map of strings
- invalid request
- unsupported field type for multipart.FileHeader
AI-assisted analysis of gin-gonic/gin@34dac209ff (2026-08-04).
Data as JSON: /data/errors/631c810497f68487.json.
Report an issue: GitHub.