Hmbown/CodeWhale · error · Error

unknown command

Error message

unknown command ${cmd}

What it means

Command dispatch guard in facts-publish.mjs: the first CLI argument (cmd) is not one of the script's known subcommands (e.g. publish/revoke-style operations). It fires before any PostgREST/network work, telling the operator the requested operation does not exist rather than guessing an intent.

Solutions

  1. Run the script with one of the supported subcommands (e.g. publish, revoke)
  2. Check `node web/scripts/facts-publish.mjs` usage/header comments for valid subcommands
  3. Quote-check for typos in the subcommand name

Example fix

// before
node web/scripts/facts-publish.mjs push --channel stable
// after
node web/scripts/facts-publish.mjs publish --channel stable
Defensive patterns

Strategy: validation

Validate before calling

const VALID = new Set(["publish", "revoke"]); // extend per script
if (!VALID.has(cmd)) {
  throw new Error(`unknown subcommand: ${cmd}; expected one of ${[...VALID]}`);
}

Try / catch

try {
  await run(["node", "web/scripts/facts-publish.mjs", ...args]);
} catch (e) {
  if (e.message.startsWith("unknown command")) {
    console.error(`${e.message} — see script header for supported subcommands`);
  }
}

Prevention

When it happens

Trigger: Calling the script with a typo'd or unsupported first argument, e.g. `facts-publish pulish`, `facts-publish list`, or no subcommand logic matching the given cmd.

Common situations: Shell alias mistakes, following outdated docs that reference a removed subcommand, forgetting the subcommand entirely so an empty/odd cmd reaches dispatch.

Understand the failure class

Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at web/scripts/facts-publish.mjs:620

    const channel = String(flags.channel ?? "");
    const version = Number(flags.version);
    const reason = String(flags.reason ?? "");
    if (!CHANNEL_RE.test(channel) || !Number.isSafeInteger(version) || version <= 0 || !reason) throw new Error("--channel, --version and --reason are required");
    if (flags["dry-run"]) {
      console.log(JSON.stringify({ dry_run: true, channel, facts_version: version, status: "revoked", revoke_reason: reason }, null, 2));
      return 0;
    }
    const channels = await postgrest(`facts_channel?scope=eq.global&slug=eq.${encodeURIComponent(channel)}&select=id`);
    if (!channels?.length) throw new Error(`channel ${channel} does not exist`);
    const updated = await postgrest(`facts_release?channel_id=eq.${channels[0].id}&facts_version=eq.${version}`, {
      method: "PATCH",
      body: { status: "revoked", revoked_at: nowIso(), revoke_reason: reason },
      prefer: "return=representation",
    });
    console.log(JSON.stringify({ revoked: updated?.length ?? 0, channel, facts_version: version }, null, 2));
    return 0;
  }
  throw new Error(`unknown command ${cmd}`);
}

const invokedDirectly = process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url);
if (invokedDirectly) {
  main(process.argv.slice(2)).then((code) => process.exit(code)).catch((err) => {
    console.error(`facts-publish: ${err.message}`);
    process.exit(1);
  });
}

View on GitHub (pinned to 433685b202)