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

  1. Use GET on the 'package/{id}/{version}/{file}' route for downloads, not the publish/delete resource
  2. Use PUT to publish and DELETE to remove packages on this resource
  3. Point 'dotnet nuget' / Visual Studio at the service index so clients pick the correct resource URLs
  4. 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

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


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/5fe88219dad78942. Report an issue: GitHub.