theonedev/onedev · error · ClientException

DENIED

DENIED

Error message

Manifest exceeds maximum size: ${MAX_MANIFEST_SIZE}

What it means

Manifest PUT bodies are capped at MAX_MANIFEST_SIZE bytes; copyWithMaxSize returns -1 when the input exceeds that limit and the registry rejects the manifest with 406 and code DENIED. This protects the server from oversized/hostile payloads, since manifests are small JSON documents by spec.

Source

Thrown at server-plugin/server-plugin-pack-container/src/main/java/io/onedev/server/plugin/pack/container/ContainerServlet.java:284

								response.getOutputStream());
					}
				} else if (method.equals("DELETE")) {
					throw new ClientException(SC_METHOD_NOT_ALLOWED, ErrorCode.UNSUPPORTED);
				} else {
					throw new BadRequestException("Invalid http method for blob pull: " + method);
				}
			} else if ((matcher = compile("(.+)/([^/]+)/manifests/([^/]+)").matcher(pathInfo)).matches()) {
				var projectPath = matcher.group(1);
				var repository = matcher.group(2);
				var reference = matcher.group(3);
				switch (method) {
					case "PUT":
						var projectId = sessionService.call(() -> checkProject(projectPath, true).getId());
						var baos = new ByteArrayOutputStream();
						try (var is = request.getInputStream()) {
							var copied = copyWithMaxSize(is, baos, MAX_MANIFEST_SIZE);
							if (copied == -1)
								throw new ClientException(SC_NOT_ACCEPTABLE, ErrorCode.DENIED, "Manifest exceeds maximum size: " + MAX_MANIFEST_SIZE);
						}

						var bytes = baos.toByteArray();
						String hash;
						if (isTag(reference)) {
							var packBlobId = packBlobService.uploadBlob(projectId, bytes, null);
							// Do not use lamda here as it may cause compilation error on terminal
							hash = LockUtils.call(getLockName(projectId, repository), new Callable<String>() {
								@Override
								public String call() {
									return sessionService.call(new Callable<>() {

										private PackBlob loadPackBlob(Map<String, PackBlob> packBlobs, String hash, long size) {
											var packBlob = packBlobs.get(hash);
											if (packBlob == null) {
												packBlob = packBlobService.findBySha256Hash(projectId, hash);
												if (packBlob != null) {
													if (packBlob.getSize() == size)

View on GitHub (pinned to d44925c47c)

Solutions

  1. Verify the body sent to /manifests/ is actually the JSON manifest/index, not a layer or config blob.
  2. Trim the index manifest: remove unnecessary descriptors, annotations, or platforms to fit under MAX_MANIFEST_SIZE.
  3. Upload large payloads via the blob endpoints; manifests must stay small by spec.
  4. Check the client (buildkit/kaniko/buildah version) for known bugs generating bloated manifests; upgrade.

Example fix

// before
curl -X PUT --data-binary @layer.tgz "$reg/v2/app/manifests/1.0"  # wrong file
// after
curl -X PUT -H "Content-Type: application/vnd.oci.image.manifest.v1+json" \
     --data-binary @manifest.json "$reg/v2/app/manifests/1.0"
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
const MAX_MANIFEST_SIZE = 4 * 1024 * 1024; // match registry constant
const size = fs.statSync(manifestPath).size;
if (size > MAX_MANIFEST_SIZE) throw new Error(`manifest ${size} bytes exceeds registry limit ${MAX_MANIFEST_SIZE}`);
if (!manifestPath.endsWith('.json')) throw new Error('manifests endpoint expects JSON, not a blob');

Try / catch

catch (err) {
  if (err.status === 406 && err.code === 'DENIED' && /exceeds maximum size/.test(err.message)) {
    // shrink index manifest or fix payload; do not retry as-is
    throw new Error('Manifest too large: trim descriptors or check you are not uploading a blob');
  }
  throw err;
}

Prevention

When it happens

Trigger: PUT /v2/<name>/manifests/<reference> with a body larger than MAX_MANIFEST_SIZE — typically an image index/manifest list referencing a huge number of descriptors, an accidentally POSTed layer blob to the manifests endpoint, or a non-manifest payload sent as the body.

Common situations: Multi-arch index manifests with hundreds of platforms/atannotations pushing past the cap; CI jobs uploading the wrong file (layer tarball instead of manifest JSON) to the manifest endpoint; clients that don't enforce OCI manifest size limits when constructing index manifests.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


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