Hmbown/CodeWhale · error · Error

envelope does not verify

Error message

envelope does not verify: ${check.errors.join("; ")}

What it means

After finding the pinned active key, activePublishingKey calls verifyEnvelope(envelope, key.publicKey) and refuses publication when the cryptographic check fails, surfacing verifyEnvelope's error list joined by "; ". This means the Ed25519 signature, canonical payload encoding, or envelope fields did not validate against the pinned public key.

Solutions

  1. Read the check.errors list in the message to identify the exact failing verification (signature mismatch, bad encoding, missing field) and fix that specifically
  2. Re-sign the current payload with the private key corresponding to the pinned active key_id, then retry with the fresh envelope
  3. Verify the envelope bytes were not altered between signing and publishing (no editor formatting, re-encoding, or newline changes to payload_b64/signature)
Defensive patterns

Strategy: validation

Validate before calling

const check = verifyEnvelope(envelope, pinnedPublicKey);
if (!check.ok) {
  console.error("envelope will be rejected:", check.errors);
  throw new Error("re-sign the current payload with the pinned key before publishing");
}

Try / catch

try {
  await activePublishingKey(envelope, keys);
} catch (err) {
  if (err.message.startsWith("envelope does not verify:")) {
    console.error("Signature/payload verification failed:", err.message.slice("envelope does not verify: ".length));
    process.exit(1);
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling activePublishingKey with an envelope whose payload was modified after signing, signed with a different private key than the pinned public key, with a corrupted payload_b64/signature, or with fields failing verifyEnvelope's structural checks (the specific reasons appear in check.errors).

Common situations: The payload JSON was regenerated (timestamps changed) without re-signing; the envelope was built with a dev key but published against production keys; base64 payloads were mangled by copy/paste or line wrapping.

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 Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/ceb7c0f74c4a7c75. Report an issue: GitHub.

Appendix: source

Thrown at web/scripts/facts-publish.mjs:407

  const keys = [];
  const remainder = body.replace(/\{\s*keyId:\s*"([^"]+)",\s*publicKey:\s*"([^"]+)",\s*status:\s*"([^"]+)"\s*,?\s*\}/g, (_, keyId, publicKey, status) => {
    keys.push({ keyId, publicKey, status });
    return "";
  });
  if (remainder.replace(/[\s,]/g, "")) throw new Error("unparsed TypeScript TRUSTED_KEYS entry");
  return validateTrustedKeys(keys);
}

function loadTrustedKeysFromRepo() {
  const keys = parseTsKeys(readBoundedFile(resolve(WEB_ROOT, "lib/cloud-facts/keys.ts"), 64 * 1024).toString("utf8"));
  return new Map(keys.map((key) => [key.keyId, key]));
}

export function activePublishingKey(envelope, keys, now = Date.now()) {
  const key = validateTrustedKeys(keys).find((key) => key.keyId === envelope.key_id && key.status === "active");
  if (!key) throw new Error("primary signing key is not pinned and active; refusing publication");
  const check = verifyEnvelope(envelope, key.publicKey);
  if (!check.ok) throw new Error(`envelope does not verify: ${check.errors.join("; ")}`);
  if (!Number.isFinite(now) || utcTime(check.payload.published_at) > now + 300_000 ||
      (check.payload.not_after != null && utcTime(check.payload.not_after) <= now)) throw new Error("publication timestamp is future or expired");
  return { key, check };
}

function refuseUnderCi() {
  for (const marker of CI_MARKERS) {
    if (process.env[marker] && !/^(0|false|no|off)$/i.test(process.env[marker])) {
      throw new Error(`refusing to run with a secret under CI (${marker} is set); publish from the founder's machine`);
    }
  }
}

function sqlLiteral(value) {
  if (value === null || value === undefined) return "null";
  return `'${String(value).replace(/'/g, "''")}'`;
}

View on GitHub (pinned to 433685b202)