theonedev/onedev · error · ClientException

Integrity check failed:

Error message

Integrity check failed: 

What it means

npm publish attachments carry an 'integrity' field (format '<algorithm>-<base64 hash>'). The handler verifies each attachment's bytes by hashing with the declared algorithm (sha512 or sha1) and comparing to the decoded hash. A mismatch throws ClientException HTTP 400 'Integrity check failed: <fileName>'; unsupported algorithms are also rejected.

Source

Thrown at server-plugin/server-plugin-pack-npm/src/main/java/io/onedev/server/plugin/pack/npm/NpmPackHandler.java:438

											if (entry.getValue().equals(version))
												distTagsOfVersion.add(entry.getKey());
										}

										var distNode = versionMetadata.get("dist");
										versionMetadata.remove("dist");

										byte[] versionMetadataBytes = writeJson(versionMetadata);

										if (distNode != null) {
											var fileName = substringAfterLast(distNode.get("tarball").asText(), "-/");
											var fileContent = attachments.get(fileName);
											if (fileContent != null) {
												var integrity = distNode.get("integrity").asText();
												var algorithm = substringBefore(integrity, "-");
												var hash = Base64.decodeBase64(substringAfter(integrity, "-"));
												if (algorithm.equals("sha512")) {
													if (!Arrays.equals(decodeHex(Digest.sha512Of(fileContent).getHash()), hash)) {
														throw new ClientException(SC_BAD_REQUEST, "Integrity check failed: " + fileName);
													}
												} else if (algorithm.equals("sha1")) {
													if (!Arrays.equals(decodeHex(Digest.sha1Of(fileContent).getHash()), hash)) {
														throw new ClientException(SC_BAD_REQUEST, "Integrity check failed: " + fileName);
													}
												} else {
													var errorMessage = String.format("Unexpected integrity algorithm (file: %s, algorithm: %s)",
															fileName, algorithm);
													throw new ClientException(SC_BAD_REQUEST, errorMessage);
												}
												var packBlobId = packBlobService.uploadBlob(projectId, fileContent, null);
												var sha256Hash = packBlobService.load(packBlobId).getSha256Hash();
												pack.setData(new NpmData(packageMetadataBytes, versionMetadataBytes, distTagsOfVersion, fileName, sha256Hash));
												packService.createOrUpdate(pack, newArrayList(packBlobService.load(packBlobId)), true);
												response.setStatus(SC_CREATED);
											}
										}
									});

View on GitHub (pinned to d44925c47c)

Solutions

  1. Re-run npm publish so integrity is recomputed from the actual attachment bytes
  2. Verify the integrity string is '<algorithm>-<base64(hash)>' matching the exact data sent (use only sha512 or sha1)
  3. Check for proxies/AV gateways modifying request bodies
  4. Compare the local file's sha512 against the metadata integrity value before publishing

Example fix

// before (hand-built metadata)
"integrity": "sha256-..."  // unsupported algorithm
// after
"integrity": "sha512-<base64 of sha512 digest>"
Defensive patterns

Strategy: validation

Validate before calling

const crypto = require('crypto');
for (const [name, att] of Object.entries(meta._attachments)) {
  const bytes = Buffer.from(att.data, 'base64');
  const [alg, b64] = att.integrity.split('-');
  if (!['sha512','sha1'].includes(alg)) throw new Error(`Unsupported integrity algorithm: ${alg}`);
  const digest = crypto.createHash(alg).update(bytes).digest('base64');
  if (digest !== b64) throw new Error(`Integrity mismatch for ${name}`);
}

Type guard

function hasValidIntegrity(att) {
  const [alg, b64] = (att?.integrity ?? '').split('-');
  return (alg === 'sha512' || alg === 'sha1') && typeof b64 === 'string' && b64.length > 0;
}

Try / catch

try { await publish() } catch (e) { if (e.response?.status === 400 && /Integrity check failed/i.test(e.message ?? '')) { console.error('Attachment bytes do not match integrity hash — republish with standard npm client'); } else throw e }

Prevention

When it happens

Trigger: Publishing where an attachment's content differs from what its integrity hash was computed over — truncated or altered tarballs, wrong hash pasted into hand-built metadata, or an unsupported algorithm value.

Common situations: Corrupted uploads over flaky networks; scripts computing integrity over a different file version than embedded in 'data'; base64/hex encoding confusion when hand-crafting payloads; tampering or proxy rewriting of bodies.

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/796d46a01e548609. Report an issue: GitHub.