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
- Verify the file is a valid gem: run `gem specification file.gem` locally before publishing.
- Rebuild the package with `gem build *.gemspec` and re-upload.
- 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
- Run `gem specification` as a CI smoke test before publishing.
- Ensure the publish job references the .gem artifact, not other build outputs.
- Verify artifact integrity (checksum) after build and before upload.
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
- Metadata exceeds maximum size: ${MAX_METADATA_SIZE}
- Package name not found in metadata
- Package version not found in metadata
- Package already exists (name: %s, version: %s)
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/5951cdf160b95dd5.
Report an issue: GitHub.