Hmbown/CodeWhale · error · Error

Rust public key must contain 32 literal bytes

Error message

Rust public key must contain 32 literal bytes

What it means

Within a parsed TrustedKey entry, the `public_key` field must contain exactly 32 numeric literal bytes (decimal or 0x hex), matching an Ed25519 public key size. The parser throws when the encoded array does not yield exactly 32 valid byte literals, e.g. when the Rust literal was truncated, comma formatting confused the splitter, or comments/expressions remain inside the array.

Solutions

  1. Count the bytes in the offending public_key array; it must be exactly 32 numeric literals.
  2. Remove type suffixes (e.g. `12u8` → `12`) and expressions; use plain decimal or 0x hex.
  3. Regenerate the key literal from the canonical base64 key rather than hand-editing.
  4. Check for comments inside the array that survive stripping and split wrongly.

Example fix

// before (Rust)
public_key: [0x8au8, 0x1fu8, /* 30 more */],
// after
public_key: [0x8a, 0x1f, /* exactly 32 plain literals */],
Defensive patterns

Strategy: validation

Validate before calling

const m = entry.match(/public_key:\s*\[([^\]]*)\]/); const parts = m[1].split(",").map(s => s.trim()).filter(Boolean); if (parts.length !== 32 || parts.some(p => !/^(?:\d+|0x[0-9a-fA-F]+)$/.test(p))) throw new Error("bad key literal");

Try / catch

try { parseRustKeys(src); } catch (e) { if (e.message.includes("32 literal bytes")) inspectKeyArrays(src); throw e; }

Prevention

When it happens

Trigger: A TrustedKey whose public_key array has fewer/more than 32 elements, contains expressions like `0u8` suffixes or computed values, or elements that are neither decimal nor 0x-hex literals after comment stripping.

Common situations: Key was hand-edited and a byte dropped; key stored in a format the parser does not accept (e.g. string literal or `[u8; 32]` const reference); a `u8` suffix on bytes breaks the number regex.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at web/scripts/check-cloud-facts.mjs:20

/** Local source, release, pinned-key parity and public-fixture gate. */
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { validateSource, verifyEnvelope, parseTsKeys, validateTrustedKeys, readBoundedFile } from "./facts-publish.mjs";

const WEB_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const REPO_ROOT = resolve(WEB_ROOT, "..");
export { parseTsKeys };

export function parseRustKeys(text) {
  const source = text.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "");
  const tables = [...source.matchAll(/^\s*pub\s+const\s+TRUSTED_KEYS\s*:\s*&\s*\[TrustedKey\]\s*=\s*&\s*\[([\s\S]*?)\]\s*;/gm)];
  if (tables.length !== 1) throw new Error("cannot parse exactly one Rust TRUSTED_KEYS table");
  const table = tables[0];
  const body = table[1].replace(/^\s*\/\/.*$/gm, "");
  const keys = [];
  const remainder = body.replace(/TrustedKey\s*\{\s*key_id:\s*"([^"]+)",\s*public_key:\s*\[([^\]]*)\],\s*status:\s*KeyStatus::(Active|Retired)\s*,?\s*\}/g, (_, keyId, encoded, status) => {
    const pieces = encoded.split(",").map((piece) => piece.trim()).filter(Boolean);
    if (pieces.length !== 32 || pieces.some((piece) => !/^(?:\d+|0x[0-9a-fA-F]+)$/.test(piece))) throw new Error("Rust public key must contain 32 literal bytes");
    const bytes = pieces.map(Number);
    if (bytes.some((byte) => !Number.isInteger(byte) || byte < 0 || byte > 255)) throw new Error("Rust public key byte out of range");
    keys.push({ keyId, publicKey: Buffer.from(bytes).toString("base64"), status: status.toLowerCase() });
    return "";
  });
  if (remainder.replace(/[\s,]/g, "")) throw new Error("unparsed Rust TRUSTED_KEYS entry");
  return validateTrustedKeys(keys);
}

function text(path) { return readBoundedFile(path).toString("utf8"); }
function json(path) { return JSON.parse(text(path)); }

export function checkCloudFacts() {
  const failures = [];
  const source = json(resolve(REPO_ROOT, "docs/cloud-facts/stable.json"));
  for (const error of validateSource(source)) failures.push(`stable.json: ${error}`);
  if (source.channel !== "stable") failures.push("stable.json: channel must be stable");
  const latest = json(resolve(WEB_ROOT, "data/latest-published-release.json"));

View on GitHub (pinned to 433685b202)