{"record":{"id":"b048297d9446749b","repo":"ccusage/ccusage","slug":"read-cli-command-spec","errorCode":null,"errorMessage":"read CLI command spec","messagePattern":"read CLI command spec","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"rust/crates/ccusage-cli-parser/build.rs","lineNumber":23,"sourceCode":"#[path = \"src/help_codegen.rs\"]\nmod help_codegen;\n\nconst CLI_HELP_JSON: &str = \"src/cli-help.json\";\nconst CLI_COMMANDS_JSON: &str = \"src/cli-commands.json\";\n\nfn main() {\n    println!(\"cargo:rerun-if-changed={CLI_HELP_JSON}\");\n    println!(\"cargo:rerun-if-changed={CLI_COMMANDS_JSON}\");\n    generate_cli_help_rs();\n}\n\nfn out_dir_path(file_name: &str) -> PathBuf {\n    PathBuf::from(env::var_os(\"OUT_DIR\").expect(\"OUT_DIR is set by cargo\")).join(file_name)\n}\n\nfn generate_cli_help_rs() {\n    let option_source = fs::read_to_string(CLI_HELP_JSON).expect(\"read CLI help spec\");\n    let command_source = fs::read_to_string(CLI_COMMANDS_JSON).expect(\"read CLI command spec\");\n    let option_sets = serde_json::from_str::<Value>(&option_source).expect(\"parse CLI help spec\");\n    let command_spec =\n        serde_json::from_str::<Value>(&command_source).expect(\"parse CLI command spec\");\n    let output = help_codegen::generate_cli_help_source(&option_sets, &command_spec);\n    fs::write(out_dir_path(\"cli-help.rs\"), output).expect(\"write generated CLI help\");\n}\n","sourceCodeStart":5,"sourceCodeEnd":30,"githubUrl":"https://github.com/ccusage/ccusage/blob/afebc5d2e0867eafbb525d1b660ce5558c1034cc/rust/crates/ccusage-cli-parser/build.rs#L5-L30","documentation":"During build script execution (generate_cli_help_rs), the build reads CLI_COMMANDS_JSON via fs::read_to_string and unwraps with expect(\"read CLI command spec\"). If that file cannot be read — it does not exist at the expected path, the path is wrong (CARGO_MANIFEST_DIR-relative), or permissions deny read — the build script panics and cargo reports 'build script panicked at read CLI command spec', failing compilation of the ccusage-cli-parser crate.","triggerScenarios":"Running cargo build/check on ccusage-cli-parser when the CLI commands JSON spec file is missing from the package, was renamed or moved, is excluded from the published crate (wrong package.files list), or the build script is executed from a working directory where the relative path no longer resolves.","commonSituations":"Publishing/packing the crate without including the spec JSON (cargo publish missing file); regenerating the spec under a new filename without updating the build script; a fresh clone on a case-sensitive filesystem where the filename case differs.","solutions":["Verify the CLI commands JSON file exists at the path CLI_COMMANDS_JSON points to relative to CARGO_MANIFEST_DIR in the ccusage-cli-parser crate.","If building a published/packed crate, add the spec JSON to the package include list (package.files or include in Cargo.toml) so cargo publish/ship includes it.","If the spec was renamed, update the CLI_COMMANDS_JSON constant in rust/crates/ccusage-cli-parser/build.rs to the new filename.","Check filename case and permissions on the spec file, especially on Linux CI after a fresh clone."],"exampleFix":"// before (build.rs)\nconst CLI_COMMANDS_JSON: &str = \"cli-commands.json\"; // file renamed to cli-commands-spec.json\n// after\nconst CLI_COMMANDS_JSON: &str = \"cli-commands-spec.json\"; // matches file on disk\n// and ensure Cargo.toml includes it:\n// [package]\n// include = [\"cli-commands-spec.json\", \"cli-help.json\", \"src/**\"]","handlingStrategy":"validation","validationCode":"// build.rs: fail with a clear message instead of a bare panic\nlet command_source = fs::read_to_string(CLI_COMMANDS_JSON).unwrap_or_else(|e| {\n    panic!(\"read CLI command spec at {}: {e}\", CLI_COMMANDS_JSON)\n});\n// pre-flight check in CI:\n// test -f cli-commands.json || { echo \"missing cli-commands.json\"; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["List spec JSON files in Cargo.toml include/package.files so cargo publish ships them.","Verify a packed crate with cargo package --list before publishing.","Keep spec filenames and the CLI_COMMANDS_JSON constant in sync via a single source of truth.","Add a CI step that builds the crate from `cargo package` output, not just the workspace."],"tags":["build-script","io","missing-file","code-generation","cargo"],"backgroundTag":"missing-file","analyzedSha":"afebc5d2e0867eafbb525d1b660ce5558c1034cc","analyzedAt":"2026-09-02T22:50:54.420Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}