theonedev/onedev · critical · ExplicitException
Pack blob missing or corrupted: ${sha256BlobHash}
Error message
Pack blob missing or corrupted: ${sha256BlobHash} What it means
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>").
Source
Thrown at server-plugin/server-plugin-pack-pypi/src/main/java/io/onedev/server/plugin/pack/pypi/PypiPackHandler.java:270
sessionService.run(() -> {
var project = checkProject(projectId, false);
var pack = packService.findByNameAndVersion(project, TYPE, name, version);
if (pack != null) {
var data = (PypiData) pack.getData();
var sha256BlobHash = data.getSha256BlobHashes().get(fileName);
if (sha256BlobHash != null) {
PackBlob packBlob;
if ((packBlob = packBlobService.checkPackBlob(projectId, sha256BlobHash)) != null) {
response.setContentType(MediaType.APPLICATION_OCTET_STREAM);
try {
packBlobService.downloadBlob(packBlob.getProject().getId(),
packBlob.getSha256Hash(), response.getOutputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
response.setStatus(SC_OK);
} else {
throw new ExplicitException("Pack blob missing or corrupted: " + sha256BlobHash);
}
} else {
response.setStatus(SC_NOT_FOUND);
}
} else {
response.setStatus(SC_NOT_FOUND);
}
});
} else {
response.setStatus(SC_NOT_FOUND);
}
}
}
@Override
public String getApiKey(HttpServletRequest request) {
return null;
}View on GitHub (pinned to d44925c47c)
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
Defensive patterns
Strategy: fallback
Validate before calling
// detect corruption early: after download, compare hashes
import { createHash } from 'crypto';
const h = createHash('sha256').update(await fs.readFile(dest)).digest('hex');
if (expectedSha256 && h !== expectedSha256) throw new Error(`Blob corrupted: expected ${expectedSha256}, got ${h}`); Try / catch
try {
await download(filesUrl, dest);
} catch (e) {
if (/Pack blob missing or corrupted/.test(e.message)) {
console.error('Server-side blob is lost; republish the package with twine or restore from backup', e);
// fallback: fetch from an alternate index or re-run the publishing job
} else throw e;
} Prevention
- 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
When it happens
Trigger: The blob referenced by the package's PypiData.getSha256BlobHashes() map is absent from blob storage or fails checkPackBlob validation at PypiPackHandler.java:260-270.
Common situations: 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.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- Invalid blob size: %s
- Digest mismatch
- Storage not found for project: ${path}
- Blob not found: %s
- Storage directory not found for project id %s
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/1d882b9465dd2ab5.
Report an issue: GitHub.