Hmbown/CodeWhale · error · Error
bad channel slug
Error message
bad channel slug
What it means
The sign subcommand derives the channel from --channel or the source document's channel field (default "stable") and validates it against CHANNEL_RE. A slug containing characters outside the allowed set (uppercase, slashes, spaces, etc.) throws "bad channel slug".
Solutions
- Use a slug accepted by CHANNEL_RE (check its definition near the top of the script; typically lowercase [a-z0-9-])
- Fix the channel field in the source JSON or pass --channel explicitly to override it
- Run `verify` on a known-good envelope to see valid channel examples
Example fix
// before node facts-publish.mjs sign --channel "Beta/v2" // after node facts-publish.mjs sign --channel beta-v2
Defensive patterns
Strategy: validation
Validate before calling
const CHANNEL_RE = /^[a-z0-9-]+$/; // mirror the script's pattern
if (!CHANNEL_RE.test(channel)) throw new Error(`bad channel slug: ${channel}`); Try / catch
try {
await run(['sign', envelopePath, '--channel', channel]);
} catch (e) {
if (e.message === 'bad channel slug') console.error('Channel must be a lowercase slug (letters, digits, hyphens)');
throw e;
} Prevention
- Validate channel slugs in CI before signing
- Keep the source JSON's channel field in the allowed format
- Derive channel names from fixed config, not branch names
When it happens
Trigger: Running `sign --channel <bad>` with a slug failing CHANNEL_RE, or signing a source JSON whose channel field is malformed/missing-safe default is overridden with an invalid value.
Common situations: Using a channel name like "Stable" or "beta/v2"; a docs/cloud-facts/stable.json edited with a typo'd channel; CI automation injecting a branch name as the channel.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- A positive pull request number is required
- API key contains invalid control characters
- API key id must be lowercase hex characters — the part…
- API key input is unexpectedly large
- API key must be - UTF-8 bytes
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/da97382889a1cf1a.
Report an issue: GitHub.
Appendix: source
Thrown at web/scripts/facts-publish.mjs:536
try { writeFileSync(fd, privateKey.export({ type: "pkcs8", format: "pem" })); }
finally { closeSync(fd); }
const raw = rawPublicKeyFromKeyObject(publicKey);
console.log(JSON.stringify({
key_id: keyId,
algorithm: "ed25519",
public_key_b64: raw.toString("base64"),
public_key_bytes: [...raw],
private_key_file: out,
note: "Private key written with mode 0600. Move it into custody (password manager); never commit it.",
}, null, 2));
return 0;
}
if (cmd === "sign") {
refuseUnderCi();
const sourcePath = resolve(String(flags.source ?? resolve(REPO_ROOT, "docs/cloud-facts/stable.json")));
const source = readJson(sourcePath);
const channel = String(flags.channel ?? source.channel ?? "stable");
if (!CHANNEL_RE.test(channel)) throw new Error("bad channel slug");
const factsVersion = Number(flags["facts-version"] ?? source.facts_version);
if (!Number.isSafeInteger(factsVersion) || factsVersion <= 0) throw new Error("--facts-version (or source.facts_version) must be a positive integer");
const keyId = String(flags["key-id"] ?? "");
const privateKey = loadPrivateKeyFromEnv();
const publishedAt = String(flags["published-at"] ?? nowIso());
const payload = buildPayload(source, { channel, factsVersion, publishedAt });
const envelope = buildEnvelope({ privateKey, keyId, payload });
const text = `${JSON.stringify(envelope, null, 2)}\n`;
if (flags.out) {
writeFileSync(resolve(String(flags.out)), text);
console.error(`wrote ${flags.out} (channel=${channel} facts_version=${factsVersion} key_id=${keyId} sha256=${envelope.sha256})`);
} else process.stdout.write(text);
return 0;
}
if (cmd === "verify") {
const envelope = readJson(resolve(String(positional[1] ?? "")));
let pub = flags["public-key"];
if (!pub) {View on GitHub (pinned to 433685b202)