JuliusBrussee/caveman · error

usage: sign-binary-checksums.mjs <checksums.txt> <output.key

Error message

usage: sign-binary-checksums.mjs <checksums.txt> <output.keysig> <public-key.pem>

What it means

Usage error from the CLI entry block of scripts/sign-binary-checksums.mjs when the script is run directly without all three positional arguments: <checksums.txt> <output.keysig> <public-key.pem>. It fires before anything is read or signed, and the catch handler prints the message to stderr and exits 1.

Source

Thrown at scripts/sign-binary-checksums.mjs:43

    bundle?.messageSignature?.messageDigest?.digest === digest &&
    verify(
      "sha256",
      checksums,
      createPublicKey(publicKeyPEM),
      Buffer.from(bundle?.messageSignature?.signature ?? "", "base64"),
    );
}

function normalizePublicKey(value) {
  return createPublicKey(value).export({ type: "spki", format: "pem" }).toString();
}

if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
  try {
    const [checksumsPath, outputPath, publicKeyPath] = process.argv.slice(2);
    const privateKeyPEM = process.env.CAVEMAN_BINARY_SIGNING_PRIVATE_KEY_PEM;
    if (!checksumsPath || !outputPath || !publicKeyPath) {
      throw new Error("usage: sign-binary-checksums.mjs <checksums.txt> <output.keysig> <public-key.pem>");
    }
    if (!privateKeyPEM) throw new Error("CAVEMAN_BINARY_SIGNING_PRIVATE_KEY_PEM is required");
    const checksums = readFileSync(checksumsPath);
    const publicKeyPEM = readFileSync(publicKeyPath, "utf8");
    if (normalizePublicKey(privateKeyPEM) !== normalizePublicKey(publicKeyPEM)) {
      throw new Error("binary signing private key does not match committed public key");
    }
    const bundle = checksumSignatureBundle(checksums, privateKeyPEM);
    if (!verifyChecksumSignatureBundle(checksums, bundle, publicKeyPEM)) {
      throw new Error("generated checksum signature failed local verification");
    }
    writeFileSync(outputPath, `${JSON.stringify(bundle)}\n`, { mode: 0o600 });
  } catch (error) {
    process.stderr.write(`${error.message}\n`);
    process.exit(1);
  }
}

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Invoke with all three arguments: `node scripts/sign-binary-checksums.mjs <checksums.txt> <output.keysig> <public-key.pem>`.
  2. Check your release runbook/wrapper for a missing third argument — the committed public key path is mandatory.
  3. Confirm the exit is the usage path (message equals the usage string) before debugging anything else.

Example fix

# before
node scripts/sign-binary-checksums.mjs dist/checksums.txt dist/checksums.keysig
# after
node scripts/sign-binary-checksums.mjs dist/checksums.txt dist/checksums.keysig keys/binary-public.pem
Defensive patterns

Strategy: validation

Validate before calling

const args = process.argv.slice(2);
if (args.length !== 3) {
  console.error("usage: sign-binary-checksums.mjs <checksums.txt> <output.keysig> <public-key.pem>");
  process.exit(2);
}

Prevention

When it happens

Trigger: Running `node scripts/sign-binary-checksums.mjs`, or supplying only one or two of the three paths (e.g. forgetting the public-key.pem argument that lets the script self-verify against the committed key).

Common situations: First-time release signing; a wrapper script or CI job dropping an argument; copy-pasting an outdated command from docs after the CLI changed.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/1c50978c6918f343. Report an issue: GitHub.