{"record":{"id":"0a676709b75207dc","repo":"theonedev/onedev","slug":"package-already-exists-name-s-version-s","errorCode":null,"errorMessage":"Package already exists (name: %s, version: %s)","messagePattern":"Package already exists \\(name: (.+?), version: (.+?)\\)","errorType":"http","errorClass":"ClientException","httpStatus":409,"severity":"error","filePath":"server-plugin/server-plugin-pack-gem/src/main/java/io/onedev/server/plugin/pack/gem/GemPackHandler.java","lineNumber":232,"sourceCode":"\t\t\t\t\t\tdata = (GemData) pack.getData();\n\t\t\t\t\t}\n\n\t\t\t\t\tBuild build = null;\n\t\t\t\t\tif (buildId != null)\n\t\t\t\t\t\tbuild = buildService.load(buildId);\n\t\t\t\t\tpack.setBuild(build);\n\t\t\t\t\tpack.setUser(SecurityUtils.getUser());\n\t\t\t\t\tpack.setPublishDate(new Date());\n\n\t\t\t\t\tString fileName;\n\t\t\t\t\tif (StringUtils.isBlank(finalPlatform) || finalPlatform.equals(\"ruby\"))\n\t\t\t\t\t\tfileName = String.format(\"%s-%s.gem\", finalName, finalVersion).toLowerCase();\n\t\t\t\t\telse\n\t\t\t\t\t\tfileName = String.format(\"%s-%s-%s.gem\", finalName, finalVersion, finalPlatform).toLowerCase();\n\n\t\t\t\t\tif (data.getSha256BlobHashes().containsKey(fileName)) {\n\t\t\t\t\t\tvar errorMessage = String.format(\"Package already exists (name: %s, version: %s)\", finalName, finalVersion);\n\t\t\t\t\t\tthrow new ClientException(SC_CONFLICT, errorMessage);\n\t\t\t\t\t}\n\t\t\t\t\tdata.getSha256BlobHashes().put(fileName, packBlob.getSha256Hash());\n\n\t\t\t\t\tvar packBlobs = data.getSha256BlobHashes().values().stream()\n\t\t\t\t\t\t\t.map(hash -> packBlobService.findBySha256Hash(projectId, hash))\n\t\t\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t\t\t.collect(toList());\n\t\t\t\t\tpackService.createOrUpdate(pack, packBlobs, data.getSha256BlobHashes().size() == 1);\n\t\t\t\t\tresponse.setStatus(SC_OK);\n\t\t\t\t}));\n\t\t\t} finally {\n\t\t\t\tFileUtils.deleteFile(tempFile);\n\t\t\t}\n\t\t} else if (pathSegments.equals(newArrayList(\"api\", \"v1\", \"gems\", \"yank\"))) {\n\t\t\tif (!isDelete)\n\t\t\t\tthrow new ClientException(SC_METHOD_NOT_ALLOWED);\n\t\t\tString name;\n\t\t\tString version;","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-plugin/server-plugin-pack-gem/src/main/java/io/onedev/server/plugin/pack/gem/GemPackHandler.java#L214-L250","documentation":"Before writing the gem blob, the handler checks the project's existing sha256 blob hashes for a file named <name>-<version>[-<platform>].gem. If it is already present, a 409 ClientException is thrown because gems are immutable in the registry — the same name/version combination cannot be published twice.","triggerScenarios":"Re-publishing a gem with the same name and version that already exists in the project (409 SC_CONFLICT).","commonSituations":"Re-running a CI publish job without version bump; re-deploying an old branch that still builds the same version; gemspec forgot a version increment after code changes.","solutions":["Bump the version in the gemspec (semantic versioning) and rebuild, then publish.","Delete the existing package version in the project's package management UI if replacement is truly intended, then republish.","Skip the publish step when the version already exists (e.g. CI idempotency check)."],"exampleFix":"# before\ns.version = '1.0.0'\n# after\ns.version = '1.0.1'","handlingStrategy":"try-catch","validationCode":"# check if the version already exists before publishing\ncurl -fsS -u user:token \"https://onedev.example.com/~api/pack/gem/<project>\" | grep -q \"\\\"name\\\":\\\"mygem\\\",\\\"version\\\":\\\"1.0.0\\\"\" && { echo 'already published'; exit 0; }","typeGuard":null,"tryCatchPattern":"try { upload(gemFile) } catch (e) { if (e.httpStatus === 409 && /Package already exists/.test(e.message)) { log.info('version already published, skipping'); } else { throw e; } }","preventionTips":["Bump the gemspec version every release; never reuse a published version.","Make CI publish steps idempotent (skip if version exists).","Delete unwanted versions via the package UI instead of overwriting."],"tags":["gem","package-upload","conflict","duplicate"],"backgroundTag":"file-already-exists","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}