hyperledger/fabric · warning
invalid request method: %s
Error message
invalid request method: %s
What it means
The version info HTTP handler only accepts GET requests; any other HTTP method is rejected with HTTP 400 Bad Request and this message embedded in a JSON errorResponse body. It exists to enforce the handler's contract that version information is read-only. The offending method is echoed back so the caller can see what was sent.
Source
Thrown at core/operations/version.go:27
import (
"encoding/json"
"fmt"
"net/http"
"github.com/hyperledger/fabric-lib-go/common/flogging"
)
type VersionInfoHandler struct {
CommitSHA string `json:"CommitSHA,omitempty"`
Version string `json:"Version,omitempty"`
}
func (m *VersionInfoHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
switch req.Method {
case http.MethodGet:
m.sendResponse(resp, http.StatusOK, m)
default:
err := fmt.Errorf("invalid request method: %s", req.Method)
m.sendResponse(resp, http.StatusBadRequest, err)
}
}
type errorResponse struct {
Error string `json:"Error"`
}
func (m *VersionInfoHandler) sendResponse(resp http.ResponseWriter, code int, payload any) {
if err, ok := payload.(error); ok {
payload = &errorResponse{Error: err.Error()}
}
js, err := json.Marshal(payload)
if err != nil {
logger := flogging.MustGetLogger("operations.runner")
logger.Errorw("failed to encode payload", "error", err)
resp.WriteHeader(http.StatusInternalServerError)
returnView on GitHub (pinned to 2736b63f8f)
Solutions
- Issue the request with GET: curl http://<ops-host>:<ops-port>/version.
- Fix any monitoring/health-check configuration to use GET for this endpoint.
- If a preflight/intermediate proxy sends OPTIONS, exclude /version from preflight handling or accept the 400 as non-fatal.
Example fix
// before curl -X POST http://localhost:9443/version // after curl http://localhost:9443/version
Defensive patterns
Strategy: try-catch
Validate before calling
if req, err := http.NewRequest(http.MethodGet, versionURL, nil); err != nil || req.Method != http.MethodGet {
return fmt.Errorf("/version only supports GET")
} Try / catch
resp, err := http.Get(versionURL)
if err != nil { return err }
if resp.StatusCode == http.StatusBadRequest {
var e struct{ Error string `json:"Error"` }
json.NewDecoder(resp.Body).Decode(&e)
return fmt.Errorf("version endpoint rejected request (use GET): %s", e.Error)
} Prevention
- Use GET for all read-only operations-server endpoints (/version, /healthz, /logspec GET).
- Configure health checks/monitors with the correct HTTP method per endpoint.
- Treat OPTIONS preflights as non-fatal for same-origin ops traffic.
When it happens
Trigger: Sending POST, PUT, DELETE, HEAD, or OPTIONS to the peer's operations-server /version endpoint instead of GET — e.g. curl -X POST, or a monitoring tool configured with a health-check that writes.
Common situations: Automation or dashboards misconfigured to POST to /version; browsers or proxies issuing OPTIONS preflights; developers testing the endpoint with a mutation method; health-check templates that reuse a POST-based check for all endpoints.
Related errors
- form contains too many parts
- cannot open file part %s from request body
- cannot read file part %s from request body
- too few arguments
- chaincode type not supported: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/b7a0fbf1828566a5.
Report an issue: GitHub.