Hmbown/CodeWhale · error · Error

--public-key is only for offline verify/emit-sql…

Error message

--public-key is only for offline verify/emit-sql; publication requires the active pinned table

What it means

The publish subcommand refuses to accept an ad-hoc --public-key. Publication must use the active key resolved from the repo-pinned trust table (activePublishingKey), so passing --public-key with publish throws immediately to prevent uploading a key nobody has pinned. Only verify and emit-sql accept --public-key (offline use).

Solutions

  1. Remove --public-key from the publish command line
  2. Ensure the signing key is pinned with status "active" in the repo trust table so activePublishingKey resolves it
  3. Use --dry-run to confirm the resolved key before publishing
  4. If you truly need a different key, pin it first rather than passing it inline

Example fix

// before
node facts-publish.mjs publish envelope.json --public-key ~/cwf.pub
// after
node facts-publish.mjs publish envelope.json --dry-run
Defensive patterns

Strategy: validation

Validate before calling

if (cmd === 'publish' && flags['public-key'] !== undefined) throw new Error('drop --public-key: publish uses the pinned active key');

Try / catch

try {
  await run(['publish', envelopePath]);
} catch (e) {
  if (e.message.includes('only for offline verify/emit-sql')) console.error('Remove --public-key for publish; pin the key in the repo table instead');
  throw e;
}

Prevention

When it happens

Trigger: Running `publish envelope.json --public-key <key>`; scripts that generically pass --public-key to every subcommand; copy-pasting an offline-verify command line and swapping the verb to publish.

Common situations: Automating publication from a rotation flow that still carries the offline --public-key flag; misunderstanding which subcommands accept the flag; trying to publish under a key that was never pinned as active in the repo.

Understand the failure class

Background: "mutually exclusive" flag errors: what "can't supply both nx and xx", "--raw is not compatible with -i" and "cannot be used with" mean, and how to fix them — this error's family across 29 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/fdafa40881826a62. Report an issue: GitHub.

Appendix: source

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

    if (!pub) {
      const trusted = loadTrustedKeysFromRepo().get(envelope.key_id);
      if (!trusted || trusted.status !== "active") throw new Error("key is not pinned and active; use --public-key only for explicit offline verification");
      pub = trusted.publicKey;
    }
    const result = verifyEnvelope(envelope, String(pub));
    console.log(JSON.stringify({ ok: result.ok, errors: result.errors, channel: envelope.channel, facts_version: envelope.facts_version, key_id: envelope.key_id, sha256: result.sha256 ?? null }, null, 2));
    return result.ok ? 0 : 1;
  }
  if (cmd === "emit-sql") {
    const envelope = readJson(resolve(String(positional[1] ?? "")));
    let pub = flags["public-key"];
    if (!pub) pub = activePublishingKey(envelope, [...loadTrustedKeysFromRepo().values()]).key.publicKey;
    process.stdout.write(emitSql(envelope, { publishedBy: String(flags["published-by"] ?? ""), publicKeyB64: pub ? String(pub) : undefined, notes: String(flags.notes ?? "") }));
    return 0;
  }
  if (cmd === "publish") {
    const envelope = readJson(resolve(String(positional[1] ?? "")));
    if (flags["public-key"] !== undefined) throw new Error("--public-key is only for offline verify/emit-sql; publication requires the active pinned table");
    const { key, check } = activePublishingKey(envelope, [...loadTrustedKeysFromRepo().values()]);
    const pub = key.publicKey;
    const row = {
      facts_version: envelope.facts_version,
      schema_version: envelope.schema_version,
      envelope_version: envelope.envelope,
      applies_to: envelope.applies_to,
      key_id: envelope.key_id,
      payload_b64: envelope.payload_b64,
      sig_b64: envelope.sig_b64,
      sigs: envelope.sigs ?? [],
      payload: check.payload,
      published_at: envelope.published_at,
      not_after: check.payload.not_after ?? null,
      published_by: String(flags["published-by"] ?? ""),
      notes: String(flags.notes ?? ""),
    };
    if (flags["dry-run"]) {

View on GitHub (pinned to 433685b202)