{"record":{"id":"b7a0fbf1828566a5","repo":"hyperledger/fabric","slug":"invalid-request-method-s","errorCode":null,"errorMessage":"invalid request method: %s","messagePattern":"invalid request method: (.+?)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"core/operations/version.go","lineNumber":27,"sourceCode":"import (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\n\t\"github.com/hyperledger/fabric-lib-go/common/flogging\"\n)\n\ntype VersionInfoHandler struct {\n\tCommitSHA string `json:\"CommitSHA,omitempty\"`\n\tVersion   string `json:\"Version,omitempty\"`\n}\n\nfunc (m *VersionInfoHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {\n\tswitch req.Method {\n\tcase http.MethodGet:\n\t\tm.sendResponse(resp, http.StatusOK, m)\n\tdefault:\n\t\terr := fmt.Errorf(\"invalid request method: %s\", req.Method)\n\t\tm.sendResponse(resp, http.StatusBadRequest, err)\n\t}\n}\n\ntype errorResponse struct {\n\tError string `json:\"Error\"`\n}\n\nfunc (m *VersionInfoHandler) sendResponse(resp http.ResponseWriter, code int, payload any) {\n\tif err, ok := payload.(error); ok {\n\t\tpayload = &errorResponse{Error: err.Error()}\n\t}\n\tjs, err := json.Marshal(payload)\n\tif err != nil {\n\t\tlogger := flogging.MustGetLogger(\"operations.runner\")\n\t\tlogger.Errorw(\"failed to encode payload\", \"error\", err)\n\t\tresp.WriteHeader(http.StatusInternalServerError)\n\t\treturn","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/operations/version.go#L9-L45","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ncurl -X POST http://localhost:9443/version\n// after\ncurl http://localhost:9443/version","handlingStrategy":"try-catch","validationCode":"if req, err := http.NewRequest(http.MethodGet, versionURL, nil); err != nil || req.Method != http.MethodGet {\n    return fmt.Errorf(\"/version only supports GET\")\n}","typeGuard":null,"tryCatchPattern":"resp, err := http.Get(versionURL)\nif err != nil { return err }\nif resp.StatusCode == http.StatusBadRequest {\n    var e struct{ Error string `json:\"Error\"` }\n    json.NewDecoder(resp.Body).Decode(&e)\n    return fmt.Errorf(\"version endpoint rejected request (use GET): %s\", e.Error)\n}","preventionTips":["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."],"tags":["http","rest","fabric","operations-endpoint"],"backgroundTag":"method-not-allowed","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"}