{"record":{"id":"148cc0229731730b","repo":"hyperledger/fabric","slug":"response-content-type-is-application-json-only","errorCode":null,"errorMessage":"response Content-Type is application/json only","messagePattern":"response Content-Type is application/json only","errorType":"http","errorClass":null,"httpStatus":406,"severity":"warning","filePath":"orderer/common/channelparticipation/restapi.go","lineNumber":662,"sourceCode":"\th.sendResponseNotAllowed(resp, err, http.MethodGet, http.MethodPost, http.MethodPut)\n}\n\nfunc negotiateContentType(req *http.Request) (string, error) {\n\tacceptReq := req.Header.Get(\"Accept\")\n\tif len(acceptReq) == 0 {\n\t\treturn \"application/json\", nil\n\t}\n\n\toptions := strings.SplitSeq(acceptReq, \",\")\n\tfor opt := range options {\n\t\tif strings.Contains(opt, \"application/json\") ||\n\t\t\tstrings.Contains(opt, \"application/*\") ||\n\t\t\tstrings.Contains(opt, \"*/*\") {\n\t\t\treturn \"application/json\", nil\n\t\t}\n\t}\n\n\treturn \"\", errors.New(\"response Content-Type is application/json only\")\n}\n\nfunc (h *HTTPHandler) sendResponseJsonError(resp http.ResponseWriter, code int, err error) {\n\tencoder := json.NewEncoder(resp)\n\tresp.Header().Set(\"Content-Type\", \"application/json\")\n\tresp.WriteHeader(code)\n\tif err := encoder.Encode(&types.ErrorResponse{Error: err.Error()}); err != nil {\n\t\th.logger.Errorf(\"failed to encode error, err: %s\", err)\n\t}\n}\n\nfunc (h *HTTPHandler) sendResponseOK(resp http.ResponseWriter, content any) {\n\tencoder := json.NewEncoder(resp)\n\tresp.Header().Set(\"Content-Type\", \"application/json\")\n\tresp.WriteHeader(http.StatusOK)\n\tif err := encoder.Encode(content); err != nil {\n\t\th.logger.Errorf(\"failed to encode content, err: %s\", err)\n\t}","sourceCodeStart":644,"sourceCodeEnd":680,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/channelparticipation/restapi.go#L644-L680","documentation":"negotiateContentType inspects the request's Accept header and only serves responses as application/json; when no acceptable option matches (no 'application/json', 'application/*', or '*/*'), it returns this error and the caller rejects the request with HTTP 406. The channelparticipation API responds exclusively in JSON, so it refuses any Accept header that explicitly excludes JSON.","triggerScenarios":"Any channelparticipation endpoint (list all/one, fetch block, join, update, remove) called with an Accept header such as 'text/html', 'application/xml', or a list that omits application/json and wildcard types.","commonSituations":"Browsers sending 'Accept: text/html' when hitting the endpoint directly; XML-expecting clients; corporate gateways injecting restrictive Accept headers; clients explicitly setting Accept to a vendor type like application/vnd.api+json.","solutions":["Set Accept: application/json on the request","Use Accept: */* to accept any type (server will return JSON)","Remove the Accept header entirely so negotiation defaults to JSON","Remove a proxy/gateway-injected Accept header that excludes application/json"],"exampleFix":"// before\nAccept: text/html\n// after\nAccept: application/json","handlingStrategy":"validation","validationCode":"const accept = headers['Accept'];\nif (accept && !/application\\/json|application\\/\\*|\\*\\/\\*/.test(accept)) {\n  throw new Error(`channelparticipation serves JSON only; Accept header excludes it: ${accept}`);\n}","typeGuard":"function acceptsJSON(accept: string | undefined): boolean {\n  return !accept || /application\\/json|application\\/\\*|\\*\\/\\*/.test(accept);\n}","tryCatchPattern":"try {\n  const res = await fetch(url, { headers: { Accept: 'application/json' } });\n  if (res.status === 406) throw new Error('Accept header must allow application/json');\n} catch (e) {\n  if (String(e).includes('application/json')) console.error('Fix the Accept header and retry');\n  else throw e;\n}","preventionTips":["Send Accept: application/json (or */*) on all channelparticipation calls","Test endpoints with curl before wiring clients to catch header issues","Strip browser-default 'Accept: text/html' when proxying requests","Be careful with vendor MIME types like application/vnd.* that exclude plain JSON"],"tags":["http","content-negotiation","accept-header","rest-api","hyperledger-fabric"],"backgroundTag":"content-negotiation-failed","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}