theonedev/onedev · error · BadRequestException
Invalid http method for blob upload: ${method}
Error message
Invalid http method for blob upload: ${method} What it means
The blob-upload endpoint only supports POST (initiate), PATCH (chunk), PUT (finalize), GET (status), and DELETE (cancel). Any other HTTP method on /v2/<name>/blobs/uploads/<uuid> is rejected with a BadRequestException carrying this message. It indicates the client is calling the upload resource incorrectly.
Source
Thrown at server-plugin/server-plugin-pack-container/src/main/java/io/onedev/server/plugin/pack/container/ContainerServlet.java:243
}
break;
}
case "GET": {
var uploadedSize = packBlobService.getUploadFileSize(projectId, uuid);
if (uploadedSize == -1)
throw new NotFoundException(ErrorCode.BLOB_UPLOAD_UNKNOWN);
response.setStatus(SC_NO_CONTENT);
response.setHeader("Range", "0-" + (uploadedSize - 1));
response.setHeader("Docker-Upload-UUID", uuid);
break;
}
case "DELETE": {
packBlobService.cancelUpload(projectId, uuid);
response.setStatus(SC_NO_CONTENT);
break;
}
default: {
throw new BadRequestException("Invalid http method for blob upload: " + method);
}
}
} else if ((matcher = compile("(.+)/([^/]+)/blobs/([^/]+)").matcher(pathInfo)).matches()) {
var projectPath = matcher.group(1);
var digestString = matcher.group(3);
if (method.equals("GET") || method.equals("HEAD")) {
var packBlobInfo = sessionService.call(() -> {
var project = checkProject(projectPath, false);
var digest = parseDigest(digestString);
var hash = digest.getHash();
PackBlob packBlob;
if ((packBlob = packBlobService.checkPackBlob(project.getId(), hash)) != null) {
response.setStatus(SC_OK);
response.setHeader("Content-Length", String.valueOf(packBlob.getSize()));
response.setHeader("Docker-Content-Digest", digestString);
return new Pair<>(packBlob.getProject().getId(), packBlob.getSha256Hash());
} else {
throw new NotFoundException(ErrorCode.BLOB_UNKNOWN);View on GitHub (pinned to d44925c47c)
Solutions
- Use POST .../blobs/uploads/ to initiate, PATCH to append chunks, and PUT ...?digest= to finalize.
- Use GET .../blobs/<digest> (not the upload URL) to check whether a blob exists.
- Use HEAD .../blobs/<digest> for existence checks; the upload session does not support it.
- Fix the client's URL construction so upload-session and blob-fetch URLs are not mixed up.
Example fix
// before PUT /v2/app/blobs/uploads/<uuid> # wrong resource // after PUT /v2/app/blobs/uploads/<uuid>?digest=sha256:... # finalize, or GET /v2/app/blobs/sha256:... # fetch existing blob
Defensive patterns
Strategy: validation
Validate before calling
const UPLOAD_METHODS = ['POST','PATCH','PUT','GET','DELETE'];
if (!UPLOAD_METHODS.includes(method)) {
throw new Error(`Use POST/PATCH/PUT/GET/DELETE on blobs/uploads URLs, got ${method}`);
} Prevention
- Map operations to the right resources: POST=initiate, PATCH=chunk, PUT?digest=finalize.
- Existence checks: HEAD/GET on /blobs/<digest>, never on the upload session URL.
- Never PUT blobs directly to /blobs/<digest>; this registry requires the session flow.
- Sanity-check generated URLs in custom clients against the OCI distribution spec.
When it happens
Trigger: Any method other than POST/PATCH/PUT/GET/DELETE sent to a URL matching (.+)/([^/]+)/blobs/uploads/([^/]+), e.g. a PUT directly to the session URL without digest, HEAD on the upload session, or a scanner/probe hitting the upload path with OPTIONS.
Common situations: Custom clients confusing the upload session URL with the blob URL (PUT to uploads/... instead of .../blobs/<digest>); security scanners probing registry endpoints; mis-wired API wrappers calling the wrong URL template.
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
- Invalid http method for blob pull: ${method}
- Invalid http method for manifest pull: ${method}
- BLOB_UPLOAD_INVALID
- DIGEST_INVALID
- Invalid value '${value}' for ${type} '${name}'. Valid values
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/5fb6cf0dac26ce0c.
Report an issue: GitHub.