{"record":{"id":"cdd3166ea4e3043f","repo":"ccusage/ccusage","slug":"read-pricing-snapshot-from-ccusage-pricing-json-pa","errorCode":null,"errorMessage":"read pricing snapshot from CCUSAGE_PRICING_JSON_PATH","messagePattern":"read pricing snapshot from CCUSAGE_PRICING_JSON_PATH","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust/crates/ccusage-core/build.rs","lineNumber":24,"sourceCode":"#[cfg(feature = \"fetch-litellm-pricing\")]\nconst LITELLM_PRICING_JSON: &str = \"model_prices_and_context_window.json\";\nconst OUT_PRICING_JSON: &str = \"litellm-pricing.json.deflate\";\nconst MODELS_DEV_PRICING_JSON: &str = \"src/models-dev-pricing.json\";\nconst OUT_MODELS_DEV_PRICING_JSON: &str = \"models-dev-pricing.json.deflate\";\nconst MODELS_DEV_CATALOG_RULES_JSON: &str = \"src/models-dev-catalog-rules.json\";\nconst OUT_MODELS_DEV_CATALOG_RULES_JSON: &str = \"models-dev-catalog-rules.json.deflate\";\nconst PRICING_JSON_PATH_ENV: &str = \"CCUSAGE_PRICING_JSON_PATH\";\n#[cfg(feature = \"fetch-litellm-pricing\")]\nconst PRICING_FETCH_TIMEOUT_SECONDS: u64 = 10;\n\nfn main() {\n    println!(\"cargo:rerun-if-env-changed={PRICING_JSON_PATH_ENV}\");\n\n    let out_path = out_dir_path(OUT_PRICING_JSON);\n    let pricing_json = if let Some(path) = env::var_os(PRICING_JSON_PATH_ENV) {\n        let path = PathBuf::from(path);\n        println!(\"cargo:rerun-if-changed={}\", path.display());\n        fs::read_to_string(path).expect(\"read pricing snapshot from CCUSAGE_PRICING_JSON_PATH\")\n    } else {\n        println!(\"cargo:rerun-if-changed={FLAKE_LOCK_JSON}\");\n        fetch_pricing_json()\n    };\n    let pricing_json = compact_pricing_json(&pricing_json).expect(\"compact LiteLLM pricing JSON\");\n\n    fs::write(out_path, deflate(pricing_json.as_bytes()))\n        .expect(\"write build-time pricing snapshot\");\n\n    embed_snapshot(MODELS_DEV_PRICING_JSON, OUT_MODELS_DEV_PRICING_JSON);\n    embed_snapshot(\n        MODELS_DEV_CATALOG_RULES_JSON,\n        OUT_MODELS_DEV_CATALOG_RULES_JSON,\n    );\n}\n\n/// The committed snapshots stay indented so their regeneration diffs stay\n/// reviewable, but they are embedded verbatim, so the indentation - and, at","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/ccusage/ccusage/blob/afebc5d2e0867eafbb525d1b660ce5558c1034cc/rust/crates/ccusage-core/build.rs#L6-L42","documentation":"The ccusage-core build script panics with \"read pricing snapshot from CCUSAGE_PRICING_JSON_PATH\" when the CCUSAGE_PRICING_JSON_PATH environment variable is set but the file it points to cannot be read by fs::read_to_string — typically the file does not exist or is not readable. This env-var path lets builds embed a local LiteLLM pricing snapshot instead of fetching via flake.lock, so a bad path breaks the build immediately.","triggerScenarios":"Building ccusage-core with CCUSAGE_PRICING_JSON_PATH set to a missing file, a directory, an unreadable file (permissions), or a path with a typo; also when the snapshot file was deleted or renamed after being exported in the environment or CI config.","commonSituations":"CI secret/config points at a path not checked out or downloaded in an earlier step; a developer sets the env var in .envrc/shell profile pointing to an old snapshot location; a relative path resolves against a different CWD during cargo build; file downloaded but under a different name.","solutions":["Verify the path exists: `ls -l \"$CCUSAGE_PRICING_JSON_PATH\"`; correct the env var or restore/download the snapshot file to that path.","Use an absolute path (or resolve it in CI before cargo runs) since the build script's CWD may differ from your shell's.","Check read permissions on the file and containing directories (`chmod a+r snapshot.json`).","Unset CCUSAGE_PRICING_JSON_PATH if you did not intend a local snapshot, letting the build fetch pricing via flake.lock instead."],"exampleFix":"// before\nexport CCUSAGE_PRICING_JSON_PATH=./litellm_prices.json   # file not there\n// after\nexport CCUSAGE_PRICING_JSON_PATH=\"$PWD/artifacts/litellm_prices.json\"\nls -l \"$CCUSAGE_PRICING_JSON_PATH\" && cargo build","handlingStrategy":"validation","validationCode":"[ -n \"$CCUSAGE_PRICING_JSON_PATH\" ] && [ -f \"$CCUSAGE_PRICING_JSON_PATH\" ] && [ -r \"$CCUSAGE_PRICING_JSON_PATH\" ] && echo OK || echo \"set CCUSAGE_PRICING_JSON_PATH to an existing readable file (absolute path recommended)\"","typeGuard":null,"tryCatchPattern":"let pricing_json = match env::var_os(PRICING_JSON_PATH_ENV) {\n    Some(p) => fs::read_to_string(PathBuf::from(&p))\n        .unwrap_or_else(|e| panic!(\"read pricing snapshot from {PRICING_JSON_PATH_ENV}={}: {e}\", p.to_string_lossy())),\n    None => fetch_pricing_json(),\n};","preventionTips":["Always use absolute paths for CCUSAGE_PRICING_JSON_PATH in CI and direnv configs","Add a build/CI step that downloads the snapshot before cargo runs, with an existence check","Unset the env var when you want the default flake.lock-based fetch instead","Keep the snapshot filename stable across artifact-generation steps"],"tags":["build-script","env-var","filesystem","io","pricing"],"backgroundTag":"missing-env-var-file","analyzedSha":"afebc5d2e0867eafbb525d1b660ce5558c1034cc","analyzedAt":"2026-09-02T22:50:54.420Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}