{"record":{"id":"1d882b9465dd2ab5","repo":"theonedev/onedev","slug":"pack-blob-missing-or-corrupted-sha256blobhash-1d882b","errorCode":null,"errorMessage":"Pack blob missing or corrupted: ${sha256BlobHash}","messagePattern":"Pack blob missing or corrupted: (.+?)","errorType":"exception","errorClass":"ExplicitException","httpStatus":null,"severity":"critical","filePath":"server-plugin/server-plugin-pack-pypi/src/main/java/io/onedev/server/plugin/pack/pypi/PypiPackHandler.java","lineNumber":270,"sourceCode":"\t\t\t\tsessionService.run(() -> {\n\t\t\t\t\tvar project = checkProject(projectId, false);\n\t\t\t\t\tvar pack = packService.findByNameAndVersion(project, TYPE, name, version);\n\t\t\t\t\tif (pack != null) {\n\t\t\t\t\t\tvar data = (PypiData) pack.getData();\n\t\t\t\t\t\tvar sha256BlobHash = data.getSha256BlobHashes().get(fileName);\n\t\t\t\t\t\tif (sha256BlobHash != null) {\n\t\t\t\t\t\t\tPackBlob packBlob;\n\t\t\t\t\t\t\tif ((packBlob = packBlobService.checkPackBlob(projectId, sha256BlobHash)) != null) {\n\t\t\t\t\t\t\t\tresponse.setContentType(MediaType.APPLICATION_OCTET_STREAM);\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tpackBlobService.downloadBlob(packBlob.getProject().getId(),\n\t\t\t\t\t\t\t\t\t\t\tpackBlob.getSha256Hash(), response.getOutputStream());\n\t\t\t\t\t\t\t\t} catch (IOException e) {\n\t\t\t\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tresponse.setStatus(SC_OK);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrow new ExplicitException(\"Pack blob missing or corrupted: \" + sha256BlobHash);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresponse.setStatus(SC_NOT_FOUND);\t\t\t\t\t\t\t\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});\n\t\t\t} else {\n\t\t\t\tresponse.setStatus(SC_NOT_FOUND);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getApiKey(HttpServletRequest request) {\n\t\treturn null;\n\t}","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-plugin/server-plugin-pack-pypi/src/main/java/io/onedev/server/plugin/pack/pypi/PypiPackHandler.java#L252-L288","documentation":"When downloading /~pypi/files/<name>/<version>/<fileName>, the pack record and its recorded sha256 blob hash exist, but checkPackBlob cannot find a valid PackBlob for that hash — the underlying blob object is missing from storage or fails integrity checks. The handler throws ExplicitException(\"Pack blob missing or corrupted: <hash>\").","triggerScenarios":"The blob referenced by the package's PypiData.getSha256BlobHashes() map is absent from blob storage or fails checkPackBlob validation at PypiPackHandler.java:260-270.","commonSituations":"Blob storage directory moved/deleted or partially restored from backup; server storage migration losing blob files; manual cleanup of blob directories; disk corruption; interrupted blob upload leaving the pack record but not the blob.","solutions":["Check the pack blob storage directory for the file named by the reported sha256 hash","Restore the missing blob from backups, or re-run the upload job that produced it","Delete and republish the affected package version via twine to recreate the blob","Verify disk integrity / any storage migration completed (no partial copies)","Enable blob integrity checks/maintenance jobs if available to detect corruption early"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// detect corruption early: after download, compare hashes\nimport { createHash } from 'crypto';\nconst h = createHash('sha256').update(await fs.readFile(dest)).digest('hex');\nif (expectedSha256 && h !== expectedSha256) throw new Error(`Blob corrupted: expected ${expectedSha256}, got ${h}`);","typeGuard":null,"tryCatchPattern":"try {\n  await download(filesUrl, dest);\n} catch (e) {\n  if (/Pack blob missing or corrupted/.test(e.message)) {\n    console.error('Server-side blob is lost; republish the package with twine or restore from backup', e);\n    // fallback: fetch from an alternate index or re-run the publishing job\n  } else throw e;\n}","preventionTips":["Don't delete or manually prune the pack blob storage directory","Verify backups include the blob store, not just the database","Complete storage migrations fully before serving packages","Republish packages if blob files were lost; keep an external index mirror for critical packages"],"tags":["pypi","storage","checksum","data-loss"],"backgroundTag":"checksum-mismatch","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}