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
- Remove --public-key from the publish command line
- Ensure the signing key is pinned with status "active" in the repo trust table so activePublishingKey resolves it
- Use --dry-run to confirm the resolved key before publishing
- 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
- Keep publish invocations minimal: no key overrides
- Use --dry-run to inspect the resolved publishing key
- Pin rotation keys in the repo before publishing under them
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
- bad channel slug
- Choose one input source, an unused --output path (or…
- key is not pinned and active; use --public-key only for…
- Use one of: a prompt, --status, --list, --show
- --write-receipt and --check-receipt are mutually exclusive
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)