hyperledger/fabric · warning
invalid request method: %s
Error message
invalid request method: %s
What it means
serveNotAllowed is the catch-all for requests whose HTTP method is not registered for the matched route. It returns 405 (via sendResponseNotAllowed) with an 'invalid request method: %s' message, and if the route includes a block ID it advertises GET as the only allowed method. It exists to give clients a precise, machine-readable rejection when they use the wrong verb.
Source
Thrown at orderer/common/channelparticipation/restapi.go:632
switch err {
case types.ErrSystemChannelExists:
h.sendResponseNotAllowed(resp, errors.WithMessage(err, "cannot remove"), http.MethodGet)
case types.ErrChannelNotExist:
h.sendResponseJsonError(resp, http.StatusNotFound, errors.WithMessage(err, "cannot remove"))
case types.ErrChannelPendingRemoval:
h.sendResponseJsonError(resp, http.StatusConflict, errors.WithMessage(err, "cannot remove"))
default:
h.sendResponseJsonError(resp, http.StatusBadRequest, errors.WithMessage(err, "cannot remove"))
}
}
func (h *HTTPHandler) serveBadContentType(resp http.ResponseWriter, req *http.Request) {
err := errors.Errorf("unsupported Content-Type: %s", req.Header.Values("Content-Type"))
h.sendResponseJsonError(resp, http.StatusBadRequest, err)
}
func (h *HTTPHandler) serveNotAllowed(resp http.ResponseWriter, req *http.Request) {
err := errors.Errorf("invalid request method: %s", req.Method)
if _, ok := mux.Vars(req)[blockIDKey]; ok {
h.sendResponseNotAllowed(resp, err, http.MethodGet)
return
}
if _, ok := mux.Vars(req)[channelIDKey]; ok {
h.sendResponseNotAllowed(resp, err, http.MethodGet, http.MethodDelete)
return
}
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", nilView on GitHub (pinned to 2736b63f8f)
Solutions
- Use the correct verb: POST to join, PUT to update (with channel ID in path), GET to list/fetch, DELETE to remove
- Read the Allow header on the 405 response — it lists the accepted methods for the route
- If a block ID is in the path, use GET (fetch-block only supports GET)
- Update scripts/tools that target the older pre-2.5 channel creation APIs
Example fix
// before DELETE /participation/channels/mychannel/blocks/latest // after GET /participation/channels/mychannel/blocks/latest
Defensive patterns
Strategy: validation
Validate before calling
const allowed = { 'POST': '/participation/channels', 'PUT': `/participation/channels/${cid}`, 'GET': `/participation/channels/${cid}/blocks/${b}`, 'DELETE': `/participation/channels/${cid}` };
const expected = Object.entries(allowed).find(([, u]) => url.endsWith(u.replace(cid, cid)));
if (method !== 'GET' && url.includes('/blocks/')) throw new Error('fetch-block only supports GET'); Type guard
type ChannelMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
function isAllowedMethod(m: string, hasBlockID: boolean): m is ChannelMethod {
return hasBlockID ? m === 'GET' : ['GET', 'POST', 'PUT', 'DELETE'].includes(m);
} Try / catch
try {
const res = await fetch(url, { method });
if (res.status === 405) {
const allow = res.headers.get('Allow');
throw new Error(`Use one of: ${allow}`);
}
} catch (e) {
if (String(e).startsWith('Use one of:')) console.error('Wrong HTTP method for this route:', e.message);
else throw e;
} Prevention
- Map endpoints to verbs: join=POST, update=PUT, list/fetch=GET, remove=DELETE
- Honor the Allow header returned with 405 responses
- fetch-block endpoints accept GET only
- Update legacy scripts that used the pre-2.5 channel APIs
When it happens
Trigger: Sending an unsupported method to any channelparticipation endpoint, e.g. POST to /participation/channels/{id} (only GET/DELETE allowed), DELETE on the fetch-block route, or PUT on list endpoints.
Common situations: Swapping PUT/POST for join vs update; using DELETE where the API expects GET for listing; generic API clients auto-negotiating methods; scripts copied from older Fabric versions where the method mapping differed.
Related errors
- missing channel ID
- missing block ID
- unsupported Content-Type: %s
- response Content-Type is application/json only
- reading http response body: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/35c4dbabaca96fb4.
Report an issue: GitHub.