JuliusBrussee/caveman · error
unsupported unsigned verification coverage
Error message
unsupported unsigned verification coverage ${String(bundle.verification_coverage)} What it means
Thrown by embeddedReceiptKeys when an unsigned bundle declares a verification_coverage value other than INCLUDED_RECEIPTS_ONLY. Unsigned exports can only attest that the receipts they physically contain verify; any other coverage claim (e.g. claiming coverage of all historical receipts) is unsupported and rejected.
Solutions
- Set verification_coverage to the INCLUDED_RECEIPTS_ONLY value (or remove the field) in the unsigned bundle.
- Re-export with the official unsigned export command, which always writes the supported coverage value.
- If you need broader coverage attestation, use the signed export path instead.
Example fix
// before
{"verification_coverage": "all_receipts", ...}
// after
{"verification_coverage": "included_receipts_only", ...} Defensive patterns
Strategy: validation
Validate before calling
if (bundle.verification_coverage !== undefined && bundle.verification_coverage !== 'included_receipts_only') throw new Error('unsigned bundle must use included_receipts_only coverage'); Type guard
function hasSupportedCoverage(b: { verification_coverage?: unknown }): boolean {
return b.verification_coverage === undefined || b.verification_coverage === 'included_receipts_only';
} Try / catch
try {
verifyBundle(bundle);
} catch (e) {
if ((e as Error).message.includes('verification coverage')) console.error('unsigned bundles may only claim included-receipts coverage');
throw e;
} Prevention
- Only produce unsigned bundles via the official export command.
- Do not copy signed-export metadata fields into unsigned bundles.
- Use signed exports when broader coverage claims are needed.
When it happens
Trigger: Verifying an unsigned bundle whose verification_coverage field is set to a value other than the INCLUDED_RECEIPTS_ONLY sentinel — typically produced by tweaking export options or hand-editing the field.
Common situations: Hand-editing the bundle to claim fuller coverage; an exporter bug writing the wrong coverage constant; mixing signed-export fields into an unsigned bundle.
Related errors
- has unsupported algorithm
- assembly slot has unknown stability
- assembly slot has unknown stability
- bedrock endpoint must be runtime or mantle
- bundle completeness cannot be attested by unsigned export…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/825cf3b62b030a43.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/index.ts:17868
if (typeof info.key !== "string" || !info.key.trim()) throw new Error(`${label} key is required`);
const raw = Buffer.from(info.key, "base64");
if (raw.length !== 32 || raw.toString("base64") !== info.key) throw new Error(`${label} must be a canonical base64 Ed25519 public key`);
return { info, raw, key: ed25519PublicKey(raw) };
}
function decodeUniqueKeyring(infos: ReceiptPublicKey[], label: string): Map<string, DecodedReceiptKey> {
const keys = new Map<string, DecodedReceiptKey>();
for (const [index, info] of infos.entries()) {
const decoded = decodeReceiptKey(info, `${label}[${index}]`);
if (keys.has(decoded.info.key_id)) throw new Error(`${label} contains duplicate key_id ${decoded.info.key_id}`);
keys.set(decoded.info.key_id, decoded);
}
return keys;
}
function embeddedReceiptKeys(bundle: ReceiptBundle): { current: DecodedReceiptKey; keys: Map<string, DecodedReceiptKey> } {
if (bundle.schema !== RECEIPT_BUNDLE_V1 && bundle.schema !== RECEIPT_BUNDLE_V2) throw new Error(`unsupported bundle schema ${String(bundle.schema)}`);
if (bundle.verification_coverage !== undefined && bundle.verification_coverage !== INCLUDED_RECEIPTS_ONLY) throw new Error(`unsupported unsigned verification coverage ${String(bundle.verification_coverage)}`);
if (bundle.completeness_attested === true) throw new Error("bundle completeness cannot be attested by unsigned export metadata");
const current = decodeReceiptKey(bundle.public_key, "public_key");
if (bundle.public_keys !== undefined && !Array.isArray(bundle.public_keys)) throw new Error("public_keys must be an array");
if (bundle.schema === RECEIPT_BUNDLE_V2 && (!Array.isArray(bundle.public_keys) || bundle.public_keys.length === 0)) throw new Error("v2 bundle requires public_keys");
const keys = decodeUniqueKeyring(bundle.public_keys ?? [], "public_keys");
const currentInRing = keys.get(current.info.key_id);
if (currentInRing && !currentInRing.raw.equals(current.raw)) throw new Error(`public_key conflicts with public_keys entry ${current.info.key_id}`);
if (bundle.schema === RECEIPT_BUNDLE_V2 && !currentInRing) throw new Error("v2 public_keys must include public_key");
if (!currentInRing) keys.set(current.info.key_id, current);
return { current, keys };
}
async function pinnedReceiptKeys(file: string, current: DecodedReceiptKey): Promise<{ keys: Map<string, DecodedReceiptKey>; trust: string }> {
const source = (await readFile(file, "utf8")).trim();
if (!source.startsWith("{")) {
const pinned = decodeReceiptKey({ ...current.info, key: source }, "--pubkey");
if (!pinned.raw.equals(current.raw)) throw new Error("bundle public key does not match the published --pubkey");
return { keys: new Map([[current.info.key_id, pinned]]), trust: "pinned_public_key" };View on GitHub (pinned to 3ee70a1026)