paperclipai/paperclip · error · Error

Artifact source identity mismatch.

Error message

Artifact source identity mismatch.

What it means

The cloud migrator artifacts script throws this from assertManifest when the manifest does not correspond to the expected source: version is not 1, sourceSha differs from the provided sha, or packageVersion does not equal versionFor(sha). It binds the artifact set to an exact source revision so you never install artifacts built from different code.

Solutions

  1. Regenerate/fetch the manifest for the current source SHA so sourceSha and packageVersion match.
  2. Update your checkout to the SHA the manifest was built from (manifest.sourceSha).
  3. Clear cached/stale manifests from prior runs and re-download.
  4. If the manifest version is not 1, upgrade the consuming tooling to the expected format.
Defensive patterns

Strategy: validation

Validate before calling

if (manifest?.version !== 1) throw new Error('Unsupported manifest version');
if (manifest.sourceSha !== currentSha) throw new Error(`Manifest is for ${manifest.sourceSha}, checkout is ${currentSha}; re-fetch artifacts`);

Type guard

const manifestMatchesSource = (m, sha) => m?.version === 1 && m.sourceSha === sha && typeof m.packageVersion === 'string';

Try / catch

try { assertManifest(manifest, sha); } catch (e) {
  if (e.message === 'Artifact source identity mismatch.') {
    manifest = await fetchManifestFor(sha); // re-download for the current source
  } else throw e;
}

Prevention

When it happens

Trigger: Calling assertManifest(manifest, sha) where manifest.version !== 1, manifest.sourceSha !== sha (checkout/tag mismatch), or manifest.packageVersion !== versionFor(sha) (artifacts published for a different commit).

Common situations: Running the migrator after pulling new commits while reusing a cached manifest; a release pipeline that published artifacts for a different SHA; hand-editing packageVersion; using an older manifest format (version !== 1).

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/c3073e6788fe4be8. Report an issue: GitHub.

Appendix: source

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

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}`];
    const expected = manifest.packages[name];
    if (pin?.version !== version || pin.integrity !== expected.integrity || pin.resolved !== expected.url || pin.link || pin.inBundle) throw new Error("Migrator lockfile package pin mismatch.");
  }
  if (lock.packages["node_modules/@paperclipai/db"].dependencies?.["@paperclipai/shared"] !== version) throw new Error("Migrator shared dependency mismatch.");
  for (const [key, entry] of Object.entries(lock.packages)) {
    if (key === "") continue;
    if (!entry || typeof entry !== "object" || entry.link) throw new Error("Invalid migrator lockfile entry.");
    if (/(?:^|\/)node_modules\/@paperclipai\/[^/]+$/.test(key) && !names.some((name) => key === `node_modules/@paperclipai/${name}`)) throw new Error("Unexpected internal migrator dependency.");

View on GitHub (pinned to 3f1d897a7c)