theonedev/onedev · error · ClientException

Metadata not found

Error message

Metadata not found

What it means

After scanning the uploaded .gem tar archive, the handler expects a metadata.gz entry whose contents describe the package. If no entry named metadata.gz was found before end-of-archive, a 400 ClientException 'Metadata not found' is thrown because the file is not a valid gem package.

Source

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

				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();
					} else if (keyNode.getValue().equals("version")) {
						var versionNode = (MappingNode) tuple.getValueNode();
						for (var versionTuple : versionNode.getValue()) {
							var versionKeyNode = (ScalarNode) versionTuple.getKeyNode();
							if (versionKeyNode.getValue().equals("version")) {
								version = ((ScalarNode) versionTuple.getValueNode()).getValue();
								break;
							}
						}

View on GitHub (pinned to d44925c47c)

Solutions

  1. Verify the file is a valid gem: run `gem specification file.gem` locally before publishing.
  2. Rebuild the package with `gem build *.gemspec` and re-upload.
  3. Check the CI publish step is uploading the .gem artifact, not another build output.

Example fix

# before
curl -u user:token --upload-file target/app.jar .../gems
# after
gem build app.gemspec
curl -u user:token --upload-file app-1.0.0.gem .../gems
Defensive patterns

Strategy: validation

Validate before calling

# validate the artifact is a real gem before publishing
tar -tf mygem.gem | grep -q '^metadata.gz$' || { echo 'not a valid gem'; exit 1; }

Try / catch

try { upload(file) } catch (e) { if (e.httpStatus === 400 && e.message === 'Metadata not found') { failFast('artifact is not a gem'); } else { throw e; } }

Prevention

When it happens

Trigger: Uploading a file with .gem extension that is not a real gem tarball (e.g. renamed jar/zip), or a corrupted/truncated gem archive where metadata.gz is missing.

Common situations: CI pipeline publishing the wrong artifact to the gem registry endpoint; file corrupted in transit or by build tooling; manually crafted uploads.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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