{"id":"631c810497f68487","repo":"gin-gonic/gin","slug":"the-accepted-formats-are-not-offered-by-the-server","errorCode":null,"errorMessage":"the accepted formats are not offered by the server","messagePattern":"the accepted formats are not offered by the server","errorType":"http","errorClass":null,"httpStatus":406,"severity":"warning","filePath":"context.go","lineNumber":1445,"sourceCode":"\n\tcase binding.MIMEYAML, binding.MIMEYAML2:\n\t\tdata := chooseData(config.YAMLData, config.Data)\n\t\tc.YAML(code, data)\n\n\tcase binding.MIMETOML:\n\t\tdata := chooseData(config.TOMLData, config.Data)\n\t\tc.TOML(code, data)\n\n\tcase binding.MIMEPROTOBUF:\n\t\tdata := chooseData(config.PROTOBUFData, config.Data)\n\t\tc.ProtoBuf(code, data)\n\n\tcase binding.MIMEBSON:\n\t\tdata := chooseData(config.BSONData, config.Data)\n\t\tc.BSON(code, data)\n\n\tdefault:\n\t\tc.AbortWithError(http.StatusNotAcceptable, errors.New(\"the accepted formats are not offered by the server\")) //nolint: errcheck\n\t}\n}\n\n// NegotiateFormat returns an acceptable Accept format.\nfunc (c *Context) NegotiateFormat(offered ...string) string {\n\tassert1(len(offered) > 0, \"you must provide at least one offer\")\n\n\tif c.Accepted == nil {\n\t\tc.Accepted = parseAccept(c.requestHeader(\"Accept\"))\n\t}\n\tif len(c.Accepted) == 0 {\n\t\treturn offered[0]\n\t}\n\tfor _, accepted := range c.Accepted {\n\t\tfor _, offer := range offered {\n\t\t\t// According to RFC 2616 and RFC 2396, non-ASCII characters are not allowed in headers,\n\t\t\t// therefore we can just iterate over the string without casting it into []rune\n\t\t\ti := 0","sourceCodeStart":1427,"sourceCodeEnd":1463,"githubUrl":"https://github.com/gin-gonic/gin/blob/34dac209ffb6ef85cc78c5d217bbb7ad001d68fd/context.go#L1427-L1463","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nc.Negotiate(http.StatusOK, gin.Negotiate{\n    Offered:  []string{binding.MIMEJSON},\n    JSONData: payload,\n})\n// client asked for XML -> 406\n// after\nc.Negotiate(http.StatusOK, gin.Negotiate{\n    Offered:  []string{binding.MIMEJSON, binding.MIMEXML},\n    JSONData: payload,\n    XMLData:  payload,\n})","handlingStrategy":"validation","validationCode":"offered := []string{binding.MIMEJSON, binding.MIMEXML}\nif format := c.NegotiateFormat(offered...); format == \"\" {\n    c.AbortWithStatus(http.StatusNotAcceptable)\n    return\n}\nc.Negotiate(http.StatusOK, gin.Negotiate{Offered: offered, /* ... */})","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["content-negotiation","accept-header","http","go"],"analyzedSha":"34dac209ffb6ef85cc78c5d217bbb7ad001d68fd","analyzedAt":"2026-08-04T21:26:18.438Z","schemaVersion":2}