paperclipai/paperclip · error · Error

Invalid artifact integrity or size.

Error message

Invalid artifact integrity or size.

What it means

The cloud migrator artifacts script throws this from assertDescriptor when an artifact pin fails structural validation: integrity is not a sha512 base64 string of the exact form sha512-<86 chars>==, size is not a safe positive integer within maximumBytes, or the pin itself is missing. It guards against trusting malformed artifact descriptors before any download.

Solutions

  1. Regenerate the artifact manifest with the current scripts/cloud-migrator-artifacts.mjs so integrity/size are recomputed correctly.
  2. Verify pin.integrity matches /^sha512-[A-Za-z0-9+/]{86}==$/ and pin.size is a positive integer within maximumBytes.
  3. Ensure you are loading the intended manifest file and it was not truncated or hand-edited.
  4. If size exceeds maximumBytes, reduce the artifact size or adjust the trusted maximum intentionally.

Example fix

// before
"integrity": "sha512-abc123", "size": "4096"
// after
"integrity": "sha512-<86 base64 chars>==", "size": 4096
Defensive patterns

Strategy: validation

Validate before calling

const okIntegrity = (i) => typeof i === 'string' && /^sha512-[A-Za-z0-9+/]{86}==$/.test(i);
const okSize = (s) => Number.isSafeInteger(s) && s > 0 && s <= maximumBytes;
if (!okIntegrity(pin?.integrity) || !okSize(pin?.size)) throw new Error('pin malformed before use');

Type guard

const isWellFormedPin = (p) => p != null && typeof p.integrity === 'string' && /^sha512-[A-Za-z0-9+/]{86}==$/.test(p.integrity) && Number.isSafeInteger(p.size) && p.size > 0;

Try / catch

try { assertDescriptor(pin, 'tgz'); } catch (e) {
  if (e.message === 'Invalid artifact integrity or size.') {
    console.error('Regenerate the artifact manifest with the current migrator script');
  } else throw e;
}

Prevention

When it happens

Trigger: Calling assertDescriptor with a pin object that is null/undefined, has a malformed or non-string integrity, an integer-unsafe/negative/oversized size, or (implicitly) a pin produced by an older script version with a different integrity format.

Common situations: A hand-edited or corrupted manifest JSON; an artifact descriptor generated by an incompatible tool version; truncation of the integrity string during copy/paste; a size field recorded as a string.

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 paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/fdd7a27adaea1127. Report an issue: GitHub.

Appendix: source

Thrown at scripts/cloud-migrator-artifacts.mjs:26

import path from "node:path";
import { pathToFileURL } from "node:url";
import { assertMetadata, tarManifest, versionFor } from "./preview-artifacts.mjs";

export const artifactBase = "https://d1p6rlowie26tp.cloudfront.net/cloud-migrators/v1";
export const artifactBucket = "paperclipai-runner-e2e-history-078455283791-us-east-1";
const prefix = "cloud-migrators/v1/";
const names = ["db", "shared"];
const maximumBytes = 32 * 1024 * 1024;
const integrityFor = (bytes) => `sha512-${createHash("sha512").update(bytes).digest("base64")}`;

export function descriptor(bytes, extension) {
  const hash = createHash("sha512").update(bytes).digest("hex");
  return { url: `${artifactBase}/blobs/${hash}.${extension}`, integrity: integrityFor(bytes), size: bytes.length };
}

function assertDescriptor(pin, extension) {
  if (!pin || typeof pin.integrity !== "string" || !/^sha512-[A-Za-z0-9+/]{86}==$/.test(pin.integrity) ||
      !Number.isSafeInteger(pin.size) || pin.size <= 0 || pin.size > maximumBytes) throw new Error("Invalid artifact integrity or size.");
  const digest = Buffer.from(pin.integrity.slice(7), "base64");
  if (digest.toString("base64") !== pin.integrity.slice(7) || pin.url !== `${artifactBase}/blobs/${digest.toString("hex")}.${extension}`) {
    throw new Error("Artifact URL does not match its content hash and trusted origin.");
  }
}

export function assertManifest(manifest, sha) {
  if (manifest?.version !== 1 || manifest.sourceSha !== sha || manifest.packageVersion !== versionFor(sha)) throw new Error("Artifact source identity mismatch.");
  for (const name of names) assertDescriptor(manifest.packages?.[name], "tgz");
  assertDescriptor(manifest.lockfile, "json");
}

export function assertLockfile(lock, manifest) {
  const version = manifest.packageVersion;
  if (lock?.lockfileVersion !== 3 || !lock.packages || Array.isArray(lock.packages) ||
      JSON.stringify(lock.packages[""]?.dependencies) !== JSON.stringify({ "@paperclipai/db": version })) throw new Error("Invalid migrator lockfile root.");
  for (const name of names) {
    const pin = lock.packages[`node_modules/@paperclipai/${name}`];

View on GitHub (pinned to 3f1d897a7c)