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

  1. Check the pack blob storage directory for the file named by the reported sha256 hash
  2. Restore the missing blob from backups, or re-run the upload job that produced it
  3. Delete and republish the affected package version via twine to recreate the blob
  4. Verify disk integrity / any storage migration completed (no partial copies)
  5. 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

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


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/1d882b9465dd2ab5. Report an issue: GitHub.