{"record":{"id":"116db62115aed124","repo":"theonedev/onedev","slug":"pack-blob-missing-or-corrupted-sha256blobhash","errorCode":null,"errorMessage":"Pack blob missing or corrupted: ${sha256BlobHash}","messagePattern":"Pack blob missing or corrupted: (.+?)","errorType":"exception","errorClass":"ExplicitException","httpStatus":null,"severity":"error","filePath":"server-plugin/server-plugin-pack-gem/src/main/java/io/onedev/server/plugin/pack/gem/GemPackHandler.java","lineNumber":423,"sourceCode":"\t\t\tsessionService.run(() -> {\n\t\t\t\tvar project = checkProject(projectId, false);\n\t\t\t\tvar pack = findPack(project, nameAndVersion);\n\t\t\t\tif (pack != null) {\n\t\t\t\t\tvar data = (GemData) pack.getData();\n\t\t\t\t\tvar sha256BlobHash = data.getSha256BlobHashes().get(fileName);\n\t\t\t\t\tif (sha256BlobHash != null) {\n\t\t\t\t\t\tPackBlob packBlob;\n\t\t\t\t\t\tif ((packBlob = packBlobService.findBySha256Hash(projectId, sha256BlobHash)) != null) {\n\t\t\t\t\t\t\tresponse.setContentType(MediaType.APPLICATION_OCTET_STREAM);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tpackBlobService.downloadBlob(packBlob.getProject().getId(),\n\t\t\t\t\t\t\t\t\t\tpackBlob.getSha256Hash(), response.getOutputStream());\n\t\t\t\t\t\t\t} catch (IOException e) {\n\t\t\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresponse.setStatus(SC_OK);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthrow new ExplicitException(\"Pack blob missing or corrupted: \" + sha256BlobHash);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresponse.setStatus(SC_NOT_FOUND);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresponse.setStatus(SC_NOT_FOUND);\n\t\t\t\t}\n\t\t\t});\t\t\t\n\t\t} else {\n\t\t\tresponse.setStatus(SC_NOT_FOUND);\n\t\t}\n\t}\n\t\n\tprivate boolean isPrerelease(String version) {\n\t\tfor (var ch: version.toCharArray()) {\n\t\t\tif (Character.isLetter(ch))\n\t\t\t\treturn true;\n\t\t}","sourceCodeStart":405,"sourceCodeEnd":441,"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#L405-L441","documentation":"GemPackHandler.download throws this ExplicitException when serving a gem package whose stored pack blob reference exists but whose underlying blob content cannot be retrieved or whose SHA-256 hash does not match the recorded hash. It guards against serving corrupted or incomplete package data to gem clients. The blob store lookup returned null content or failed integrity verification against the persisted sha256BlobHash.","triggerScenarios":"GET request for a gem/gemspec download resolves a PackBlob by hash but PackService.downloadBlob returns null or throws because the blob file is absent from the blob store, or the recomputed SHA-256 does not equal packBlob.getSha256Hash() before streaming to response.getOutputStream().","commonSituations":"Blob store on disk was pruned/cleaned manually or by a GC bug while pack metadata rows remained; interrupted upload left a dangling reference; disk corruption or migration between OneDev instances copied the database but not the blobs directory.","solutions":["Delete the affected package version in the project's Packages screen and re-publish (gem push) so the blob is re-uploaded with a valid hash.","Check the server blob storage directory (site blobs) for the missing file and restore it from backup or another instance.","Verify disk health/free space on the OneDev server; a full disk during upload commonly produces truncated blobs.","Check server logs around the time the package was published for blob write errors."],"exampleFix":"// Not a code fix on the caller side; server-side re-publish\n# delete corrupted version in OneDev UI: Project -> Packages -> gem package -> delete version\n# then from client\ngem push mygem-1.0.0.gem","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    gemClient.fetch(spec);\n} catch (e) {\n    if (String(e).includes('missing or corrupted')) {\n        // re-push package or notify admin to restore blob store from backup\n    } else throw e;\n}","preventionTips":["Never delete or prune the OneDev blobs directory independently of the database.","Back up the server blob storage together with the database.","Monitor disk space so uploads never truncate.","After server migrations, verify package downloads work before switching traffic."],"tags":["package-management","blob-storage","integrity","rubygems"],"backgroundTag":"checksum-mismatch","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"}