theonedev/onedev · error · ClientException
405
Error message
405
What it means
The NuGet package resource under this segment only supports PUT (publish) and DELETE; any other method (GET/POST/PATCH...) reaches the else branch and throws ClientException(SC_METHOD_NOT_ALLOWED), returned as HTTP 405 with an Allow-style contract of PUT/DELETE.
Source
Thrown at server-plugin/server-plugin-pack-nuget/src/main/java/io/onedev/server/plugin/pack/nuget/NugetPackHandler.java:356
pathSegments = pathSegments.subList(1, pathSegments.size());
if (pathSegments.isEmpty()) {
logger.warn("Package version is missing");
throw new ClientException(SC_BAD_REQUEST);
}
var version = pathSegments.get(0);
LockUtils.run(getLockName(projectId, name), () -> transactionService.run(() -> {
var project = checkProject(projectId, true);
var pack = packService.findByNameAndVersion(project, TYPE, name, version);
if (pack != null) {
packService.delete(pack);
response.setStatus(SC_NO_CONTENT);
} else {
response.setStatus(SC_NOT_FOUND);
}
}));
} else {
throw new ClientException(SC_METHOD_NOT_ALLOWED);
}
} else if (currentSegment.equals("query")) {
sessionService.run(() -> {
var nameQuery = request.getParameter("q");
if (StringUtils.isBlank(nameQuery))
nameQuery = null;
else
nameQuery = decodeQuery(nameQuery);
var skip = request.getParameter("skip");
int offset = 0;
if (StringUtils.isNotBlank(skip))
offset = Integer.parseInt(skip);
var count = 0;
var take = request.getParameter("take");
if (StringUtils.isNotBlank(take))
count = Math.min(Integer.parseInt(take), MAX_QUERY_COUNT);
boolean includePrerelease = "true".equals(request.getParameter("prerelease"));View on GitHub (pinned to d44925c47c)
Solutions
- Use GET on the 'package/{id}/{version}/{file}' route for downloads, not the publish/delete resource
- Use PUT to publish and DELETE to remove packages on this resource
- Point 'dotnet nuget' / Visual Studio at the service index so clients pick the correct resource URLs
- Check proxy rewrites do not collapse distinct NuGet route prefixes into one
Example fix
// before GET /~nuget/project-x/My.Package/1.2.3/My.Package.1.2.3.nupkg # wrong route -> 405 // after GET /~nuget/project-x/package/My.Package/1.2.3/My.Package.1.2.3.nupkg
Defensive patterns
Strategy: validation
Validate before calling
// only PUT/DELETE are valid on the package resource
const allowed = ['PUT','DELETE'];
if (!allowed.includes(method)) throw new Error(`use PUT/DELETE for package resource, got ${method}`); Prevention
- Consult the NuGet v3 service index for correct resource URLs
- Keep download traffic on package/... routes
- Lint CI scripts for HTTP verbs per endpoint
When it happens
Trigger: Sending GET or POST to the package content path instead of the 'query'/'registration'/'package' read endpoints; a client misrouting download requests to the publish/delete resource; health checks hitting the package path with HEAD/GET.
Common situations: Confusing the publish endpoint (<feed> root) with download endpoints (package/{id}/{version}/{file}); older tooling versions using different NuGet resource layouts; typo'd base URLs so downloads land on the wrong resource.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Method not allowed
- Unauthenticated
- Http request failed (url: %s, status code: %d, error message
- Http request failed (status: %s)
- Method Not Allowed
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/5fe88219dad78942.
Report an issue: GitHub.