ccusage/ccusage · critical

parse CLI help spec

Error message

parse CLI help spec

What it means

generate_cli_help_rs parses the CLI help JSON with serde_json::from_str::<Value> and unwraps with expect("parse CLI help spec"). If cli-help.json (the option_source file) contains invalid JSON or a structure that cannot deserialize as serde_json::Value (practically: any malformed JSON), the build script panics with 'parse CLI help spec' and the crate fails to compile. This is the parse step for the options spec, distinct from error [3] which is the read of the commands spec.

Source

Thrown at rust/crates/ccusage-cli-parser/build.rs:24

mod help_codegen;

const CLI_HELP_JSON: &str = "src/cli-help.json";
const CLI_COMMANDS_JSON: &str = "src/cli-commands.json";

fn main() {
    println!("cargo:rerun-if-changed={CLI_HELP_JSON}");
    println!("cargo:rerun-if-changed={CLI_COMMANDS_JSON}");
    generate_cli_help_rs();
}

fn out_dir_path(file_name: &str) -> PathBuf {
    PathBuf::from(env::var_os("OUT_DIR").expect("OUT_DIR is set by cargo")).join(file_name)
}

fn generate_cli_help_rs() {
    let option_source = fs::read_to_string(CLI_HELP_JSON).expect("read CLI help spec");
    let command_source = fs::read_to_string(CLI_COMMANDS_JSON).expect("read CLI command spec");
    let option_sets = serde_json::from_str::<Value>(&option_source).expect("parse CLI help spec");
    let command_spec =
        serde_json::from_str::<Value>(&command_source).expect("parse CLI command spec");
    let output = help_codegen::generate_cli_help_source(&option_sets, &command_spec);
    fs::write(out_dir_path("cli-help.rs"), output).expect("write generated CLI help");
}

View on GitHub (pinned to afebc5d2e0)

Solutions

  1. Validate the CLI help JSON with a linter (jq . cli-help.json or any JSON validator) to find the exact syntax error and line.
  2. Fix the malformed JSON — common culprits are leftover git conflict markers, trailing commas, or a truncated file from a failed generation run.
  3. Regenerate the spec with its authoring/codegen script instead of editing it by hand.
  4. Re-encode the file as UTF-8 without BOM if an editor changed the encoding.

Example fix

// before (cli-help.json, bad merge resolution)
{
<<<<<<< HEAD
  "verbose": {"short": "v"},
=======
  "quiet": {"short": "q"}
>>>>>>> main
}
// after
{
  "verbose": {"short": "v"},
  "quiet": {"short": "q"}
}
Defensive patterns

Strategy: validation

Validate before calling

// validate spec JSON before the build script consumes it
let option_source = fs::read_to_string(CLI_HELP_JSON).expect("read CLI help spec");
serde_json::from_str::<serde_json::Value>(&option_source)
    .unwrap_or_else(|e| panic!("parse CLI help spec at {CLI_HELP_JSON}: {e}"));
// CI pre-flight:
// jq empty cli-help.json || { echo "invalid cli-help.json"; exit 1; }

Prevention

When it happens

Trigger: cargo build/check on ccusage-cli-parser when the CLI help JSON file contains a syntax error (trailing comma, unquoted key, truncated file from a failed write or bad merge conflict resolution), or the file is empty/encoded incorrectly (BOM, non-UTF8).

Common situations: A merge conflict in cli-help.json resolved by committing conflict markers (<<<<<<) into the JSON; a codegen script that wrote a partial file; editing the spec by hand and introducing a JSON syntax error; a non-UTF8 file saved by an editor.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of ccusage/ccusage@afebc5d2e0 (2026-09-02). Data as JSON: /api/errors/e0692f4534e35652. Report an issue: GitHub.