hyperledger/fabric · warning
response Content-Type is application/json only
Error message
response Content-Type is application/json only
What it means
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.
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
Example fix
// before Accept: text/html // after Accept: application/json
Defensive patterns
Strategy: validation
Validate before calling
const accept = headers['Accept'];
if (accept && !/application\/json|application\/\*|\*\/\*/.test(accept)) {
throw new Error(`channelparticipation serves JSON only; Accept header excludes it: ${accept}`);
} Type guard
function acceptsJSON(accept: string | undefined): boolean {
return !accept || /application\/json|application\/\*|\*\/\*/.test(accept);
} Try / catch
try {
const res = await fetch(url, { headers: { Accept: 'application/json' } });
if (res.status === 406) throw new Error('Accept header must allow application/json');
} catch (e) {
if (String(e).includes('application/json')) console.error('Fix the Accept header and retry');
else throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- invalid request method
- missing block ID
- missing channel ID
- unsupported Content-Type
- cannot unmarshal file part
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/148cc0229731730b.
Report an issue: GitHub.
Appendix: source
Thrown at orderer/common/channelparticipation/restapi.go:662
h.sendResponseNotAllowed(resp, err, http.MethodGet, http.MethodPost, http.MethodPut)
}
func negotiateContentType(req *http.Request) (string, error) {
acceptReq := req.Header.Get("Accept")
if len(acceptReq) == 0 {
return "application/json", nil
}
options := strings.SplitSeq(acceptReq, ",")
for opt := range options {
if strings.Contains(opt, "application/json") ||
strings.Contains(opt, "application/*") ||
strings.Contains(opt, "*/*") {
return "application/json", nil
}
}
return "", errors.New("response Content-Type is application/json only")
}
func (h *HTTPHandler) sendResponseJsonError(resp http.ResponseWriter, code int, err error) {
encoder := json.NewEncoder(resp)
resp.Header().Set("Content-Type", "application/json")
resp.WriteHeader(code)
if err := encoder.Encode(&types.ErrorResponse{Error: err.Error()}); err != nil {
h.logger.Errorf("failed to encode error, err: %s", err)
}
}
func (h *HTTPHandler) sendResponseOK(resp http.ResponseWriter, content any) {
encoder := json.NewEncoder(resp)
resp.Header().Set("Content-Type", "application/json")
resp.WriteHeader(http.StatusOK)
if err := encoder.Encode(content); err != nil {
h.logger.Errorf("failed to encode content, err: %s", err)
}View on GitHub (pinned to 2736b63f8f)