theonedev/onedev · error · ClientException

Metadata exceeds maximum size: ${MAX_METADATA_SIZE}

Error message

Metadata exceeds maximum size: ${MAX_METADATA_SIZE}

What it means

While uploading a gem, GemPackHandler scans the tar for metadata.gz and inflates it with a hard size cap (MAX_METADATA_SIZE). copyWithMaxSize signals overflow with -1 and the handler throws a 406 ClientException because the decompressed metadata would exceed the allowed limit. This guards against decompression bombs.

Source

Thrown at server-plugin/server-plugin-pack-gem/src/main/java/io/onedev/server/plugin/pack/gem/GemPackHandler.java:152

				checkProject(projectId, true);
			});
			var tempFile = FileUtils.createTempFile("upload", "gem");
			try {
				try (var os = new BufferedOutputStream(new FileOutputStream(tempFile), BUFFER_SIZE)) {
					IOUtils.copy(request.getInputStream(), os);
				} catch (IOException e) {
					throw new RuntimeException(e);
				}

				byte[] metadataBytes = null;
				try (var is = new TarArchiveInputStream(new BufferedInputStream(new FileInputStream(tempFile), BUFFER_SIZE))) {
					TarArchiveEntry entry;
					while ((entry = is.getNextTarEntry()) != null) {
						if (entry.getName().equals("metadata.gz")) {
							var baos = new ByteArrayOutputStream();
							var copied = copyWithMaxSize(new GZIPInputStream(is), baos, MAX_METADATA_SIZE);
							if (copied == -1)
								throw new ClientException(SC_NOT_ACCEPTABLE, "Metadata exceeds maximum size: " + MAX_METADATA_SIZE);
							metadataBytes = baos.toByteArray();
							break;
						}
					}
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
				if (metadataBytes == null)
					throw new ClientException(SC_BAD_REQUEST, "Metadata not found");

				String name = null;
				String version = null;
				String platform = null;
				var metadata = (MappingNode) new Yaml().compose(new InputStreamReader(new ByteArrayInputStream(metadataBytes)));
				for (var tuple : metadata.getValue()) {
					var keyNode = (ScalarNode) tuple.getKeyNode();
					if (keyNode.getValue().equals("name")) {
						name = ((ScalarNode) tuple.getValueNode()).getValue();

View on GitHub (pinned to d44925c47c)

Solutions

  1. Shrink the gem's metadata (trim gemspec: files list, description, dependencies) and rebuild.
  2. Reduce what gets packaged (use gemspec.files/filters to exclude large generated files).
  3. If legitimately huge metadata is required, increase the registry's metadata size limit in the plugin configuration/server code.

Example fix

# before
gemspec.files = Dir["**/*"]
# after
gemspec.files = Dir["lib/**/*.rb", "bin/*", "*.gemspec"]
Defensive patterns

Strategy: validation

Validate before calling

# check decompressed metadata size before upload
size=$(tar -xOf mygem.gem metadata.gz | gunzip | wc -c)
[ "$size" -lt 1048576 ] || { echo 'metadata too large'; exit 1; }

Try / catch

try { upload(gemFile) } catch (e) { if (e.httpStatus === 406 && /Metadata exceeds maximum size/.test(e.message)) { rebuildWithSmallerMetadata(); retry(); } else { throw e; } }

Prevention

When it happens

Trigger: Pushing a gem package whose metadata.gz decompresses to more than MAX_METADATA_SIZE bytes — e.g. an extremely large gemspec, or a malicious/corrupt archive with a compression bomb named metadata.gz.

Common situations: Building gems with huge embedded files listed in the gemspec; repackaging legacy gems with oversized metadata; uploading a maliciously crafted .gem to test/abuse the registry.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


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