Hmbown/CodeWhale · error · Error
--out is required (write the private key OUTSIDE any…
Error message
--out <path> is required (write the private key OUTSIDE any repository)
What it means
The keygen subcommand requires an explicit --out path where the generated ed25519 private key (PKCS#8 PEM) will be written with 0600 permissions. If the flag is absent, out resolves to null and this error is thrown, deliberately instructing you to write the key outside any repository.
Solutions
- Add --out /secure/path/outside/repo/cwf-x.pem (a directory outside any git repository)
- Ensure the parent directory exists or is creatable (the script mkdirs it with mode 0700)
- Note the file is opened O_EXCL|O_NOFOLLOW: choose a path where no file already exists
Example fix
// before node facts-publish.mjs keygen --key-id cwf-prod // after node facts-publish.mjs keygen --key-id cwf-prod --out ~/.secrets/cwf-prod.pem
Defensive patterns
Strategy: validation
Validate before calling
if (!outPath) throw new Error('keygen requires --out pointing outside any repository');
if (existsSync(outPath)) throw new Error('output file already exists (O_EXCL will fail)'); Try / catch
try {
await run(['keygen', '--key-id', keyId, '--out', outPath]);
} catch (e) {
if (e.message.includes('--out <path> is required')) console.error('Pass a path outside the repo, e.g. ~/.secrets/<key-id>.pem');
throw e;
} Prevention
- Store private keys in ~/.secrets or a secrets manager, never in the repo
- Ensure the target file does not already exist (script opens with O_EXCL)
- Run keygen locally, not under CI (refuseUnderCi blocks it anyway)
When it happens
Trigger: Running `facts-publish.mjs keygen --key-id cwf-x` without --out, or passing --out with an empty string value so flags.out is falsy.
Common situations: Following docs that show keygen without the flag; shell quoting problems making --out empty; forgetting that keys must live outside the repo to avoid committing secrets.
Understand the failure class
Background: "--flag is required" and "must specify" CLI errors: how missing-required-flag validation works and how to fix it — this error's family across 20 libraries.
Related errors
- Codewhale account login requires an OS credential manager…
- doctor configuration validation failed; details omitted…
- lane log proxy requires a command
- mimo-v2.5-tts-voiceclone requires --clone-voice <mp3|wav>…
- mimo-v2.5-tts-voicedesign requires --voice-prompt or…
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/b2e72fe23d88277a.
Report an issue: GitHub.
Appendix: source
Thrown at web/scripts/facts-publish.mjs:513
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(readBoundedFile(path)));
}
function nowIso() {
return new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
}
async function main(argv) {
const { positional, flags } = parseArgs(argv);
const cmd = positional[0];
if (!cmd || flags.help) {
console.log(readFileSync(fileURLToPath(import.meta.url), "utf8").split("\n").slice(1, 26).join("\n"));
return 0;
}
if (cmd === "keygen") {
const keyId = String(flags["key-id"] ?? "");
if (!KEY_ID_RE.test(keyId)) throw new Error("--key-id must match cwf-[a-z0-9-]{1,32}");
const out = flags.out ? resolve(String(flags.out)) : null;
if (!out) throw new Error("--out <path> is required (write the private key OUTSIDE any repository)");
refuseUnderCi();
const { privateKey, publicKey } = generateKeyPairSync("ed25519");
mkdirSync(dirname(out), { recursive: true, mode: 0o700 });
const fd = openSync(out, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0), 0o600);
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") {View on GitHub (pinned to 433685b202)