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.
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)
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
- missing channel ID
- missing block ID
- unsupported Content-Type: %s
- invalid request method: %s
- reading http response body: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/148cc0229731730b.
Report an issue: GitHub.