pbakaus/impeccable · error

usage: font-match.mjs --measure <text-region-id> | --rank <t

Error message

usage: font-match.mjs --measure <text-region-id> | --rank <text-region-id> [--candidates "Family:700,Family2:400,..."] [--text "..."] [--transform uppercase] [--category sans,serif,display,handwriting,mono]

What it means

The `font-match.mjs` verb requires exactly one mode selector: `--measure <text-region-id>` or `--rank <text-region-id>`. When neither flag (or no id value) is supplied, the tool prints this usage line to stderr and exits 1 without touching the spec. It is a pure argument-validation guard at the top of `run`.

Source

Thrown at crates/comp-verbs/src/font_match.rs:430

fn write_spec(io: &Io, spec_path: &str, spec: &Value) {
    let out = resolve(io, spec_path);
    if let Some(parent) = out.parent() {
        let _ = std::fs::create_dir_all(parent);
    }
    let _ = std::fs::write(out, util::json_pretty(spec));
}

// ---- CLI -------------------------------------------------------------------

/// `impeccable font-match --measure <id> | --rank <id> ...`
pub fn run(argv: &[String], io: &mut Io, renderer: &mut dyn FontRenderer) -> i32 {
    let spec_path = arg_or(argv, "spec", SPEC_PATH).to_string();
    let mut spec = load_spec(&resolve(io, &spec_path));
    let measure_id = arg(argv, "measure");
    let rank_id = arg(argv, "rank");
    let id = measure_id.or(rank_id);
    let Some(id) = id else {
        io.err("usage: font-match.mjs --measure <text-region-id> | --rank <text-region-id> [--candidates \"Family:700,Family2:400,...\"] [--text \"...\"] [--transform uppercase] [--category sans,serif,display,handwriting,mono]\n");
        return 1;
    };
    let Some(spec_val) = spec.as_mut() else {
        io.err(&format!("font-match: no spec at {spec_path}; run comp-spec.mjs first\n"));
        return 1;
    };
    let region = spec_val
        .get("regions")
        .and_then(Value::as_array)
        .and_then(|a| a.iter().find(|r| r.get("id").and_then(Value::as_str) == Some(id)))
        .cloned();
    let Some(region) = region else {
        let ids = spec_val
            .get("regions")
            .and_then(Value::as_array)
            .map(|a| a.iter().filter_map(|r| r.get("id").and_then(Value::as_str)).collect::<Vec<_>>().join(", "))
            .unwrap_or_default();
        io.err(&format!("font-match: no region {id}; ids: {ids}\n"));

View on GitHub (pinned to 2bc2879276)

Solutions

  1. Add exactly one of `--measure <text-region-id>` or `--rank <text-region-id>` to the invocation.
  2. Ensure the flag has a non-empty value (`--measure hero-title`, not a bare `--measure`).
  3. Check the id exists in the spec first (`comp-spec` output regions array) so the corrected call doesn't then hit the no-region error.
  4. Fix any flag typos that silently leave `measure_id` and `rank_id` unset.

Example fix

// before
node font-match.mjs --candidates "Inter:400,Söhne:700"
// after
node font-match.mjs --measure hero-title --candidates "Inter:400,Söhne:700"
Defensive patterns

Strategy: validation

Validate before calling

const mode = argv.includes('--measure') ? 'measure' : argv.includes('--rank') ? 'rank' : null;
const id = mode ? argv[argv.indexOf('--' + mode) + 1] : null;
if (!mode || !id) {
  console.error('font-match requires --measure <id> or --rank <id>');
  process.exit(1);
}

Type guard

function hasModeAndId(argv) {
  const i = argv.findIndex(a => a === '--measure' || a === '--rank');
  return i !== -1 && typeof argv[i + 1] === 'string' && argv[i + 1].length > 0;
}

Prevention

When it happens

Trigger: Calling `font-match.mjs` with no flags at all; passing `--measure` or `--rank` without an id value; passing only auxiliary flags like `--candidates`/`--text`/`--transform`/`--category` without a mode+id pair.

Common situations: Scripting the tool and forgetting the region id; copying an example that used a placeholder id; wiring the wrong argv array so the mode flag never reaches `run`; typos like `--mesure` leaving both `arg()` lookups empty.

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


AI-assisted analysis of pbakaus/impeccable@2bc2879276 (2026-09-08). Data as JSON: /api/errors/bb2f6dc717abb277. Report an issue: GitHub.