{"record":{"id":"cd93446396f31449","repo":"theonedev/onedev","slug":"method-not-allowed","errorCode":null,"errorMessage":"Method Not Allowed","messagePattern":"Method Not Allowed","errorType":"http","errorClass":"ClientException","httpStatus":405,"severity":"error","filePath":"server-plugin/server-plugin-pack-cargo/src/main/java/io/onedev/server/plugin/pack/cargo/CargoPackHandler.java","lineNumber":106,"sourceCode":"\t\tthis.objectMapper = objectMapper;\n\t}\n\n\t@Override\n\tpublic String getHandlerId() {\n\t\treturn HANDLER_ID;\n\t}\n\n\t@Override\n\tpublic void handle(HttpServletRequest request, HttpServletResponse response,\n\t\t\t\t\t   Long projectId, Long buildId, List<String> pathSegments) {\n\t\tvar method = request.getMethod();\n\t\tvar isGet = method.equals(\"GET\");\n\t\tvar isPut = method.equals(\"PUT\");\n\t\tvar isDelete = method.equals(\"DELETE\");\n\n\t\tif (pathSegments.equals(newArrayList(\"api\", \"v1\", \"crates\", \"new\"))) {\n\t\t\tif (!isPut)\n\t\t\t\tthrow new ClientException(SC_METHOD_NOT_ALLOWED);\n\t\t\tpublish(request, response, projectId, buildId);\n\t\t} else if (pathSegments.size() == 6\n\t\t\t\t&& pathSegments.subList(0, 3).equals(newArrayList(\"api\", \"v1\", \"crates\"))\n\t\t\t\t&& pathSegments.get(5).equals(\"download\")) {\n\t\t\tif (!isGet)\n\t\t\t\tthrow new ClientException(SC_METHOD_NOT_ALLOWED);\n\t\t\tdownload(response, projectId, decodePath(pathSegments.get(3)), decodePath(pathSegments.get(4)));\n\t\t} else if (pathSegments.size() == 6\n\t\t\t\t&& pathSegments.subList(0, 3).equals(newArrayList(\"api\", \"v1\", \"crates\"))\n\t\t\t\t&& pathSegments.get(5).equals(\"yank\")) {\n\t\t\tif (!isDelete)\n\t\t\t\tthrow new ClientException(SC_METHOD_NOT_ALLOWED);\n\t\t\tsetYanked(response, projectId, decodePath(pathSegments.get(3)), decodePath(pathSegments.get(4)), true);\n\t\t} else if (pathSegments.size() == 6\n\t\t\t\t&& pathSegments.subList(0, 3).equals(newArrayList(\"api\", \"v1\", \"crates\"))\n\t\t\t\t&& pathSegments.get(5).equals(\"unyank\")) {\n\t\t\tif (!isPut)\n\t\t\t\tthrow new ClientException(SC_METHOD_NOT_ALLOWED);","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-plugin/server-plugin-pack-cargo/src/main/java/io/onedev/server/plugin/pack/cargo/CargoPackHandler.java#L88-L124","documentation":"The Cargo pack registry handler routes requests under /api/v1/crates/... . Cargo's publish endpoint (/api/v1/crates/new) only accepts PUT (as cargo client uses) and download endpoints only accept GET; any other HTTP method on those paths results in a ClientException with status 405 Method Not Allowed.","triggerScenarios":"Sending POST/GET to /api/v1/crates/new instead of PUT, or POST/PUT/DELETE to a /api/v1/crates/{crate}/{version}/download path instead of GET.","commonSituations":"Manually testing the registry with curl using the wrong verb; a proxy or tool rewriting PUT to POST; scripts using generic REST conventions (POST to publish) against the cargo-compatible API.","solutions":["Use the cargo client itself: `cargo publish` issues PUT to /api/v1/crates/new; `cargo` download uses GET.","If testing manually, send `curl -X PUT` for publish (with the cargo payload) and plain GET for download URLs.","Check any reverse proxy/rewrite rules that may convert request methods."],"exampleFix":"// before\ncurl -X POST https://onedev.example.com/~builds/1/api/v1/crates/new ...\n// after\ncurl -X PUT https://onedev.example.com/~builds/1/api/v1/crates/new ...","handlingStrategy":"validation","validationCode":"const allowed = {\"/api/v1/crates/new\": [\"PUT\"], \"/api/v1/crates/download\": [\"GET\"]};\nif (!allowed[pathKey]?.includes(method)) throw new Error(\"Wrong HTTP method for \" + pathKey);","typeGuard":null,"tryCatchPattern":"try {\n    await publishPackage();\n} catch (e) {\n    if (e.response && e.response.status === 405) {\n        console.error(\"Method not allowed: use PUT for publish, GET for download\");\n    }\n}","preventionTips":["Always use the cargo client (cargo publish / cargo fetch) rather than hand-rolled HTTP calls.","Remember cargo spec: PUT /api/v1/crates/new, GET .../download.","Check proxies/rewrites don't mutate the HTTP method."],"tags":["cargo","http","method-not-allowed","registry"],"backgroundTag":"unexpected-http-status","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}