ccusage/ccusage · error
read pricing snapshot from CCUSAGE_PRICING_JSON_PATH
Error message
read pricing snapshot from CCUSAGE_PRICING_JSON_PATH
What it means
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.
Source
Thrown at rust/crates/ccusage-core/build.rs:24
#[cfg(feature = "fetch-litellm-pricing")]
const LITELLM_PRICING_JSON: &str = "model_prices_and_context_window.json";
const OUT_PRICING_JSON: &str = "litellm-pricing.json.deflate";
const MODELS_DEV_PRICING_JSON: &str = "src/models-dev-pricing.json";
const OUT_MODELS_DEV_PRICING_JSON: &str = "models-dev-pricing.json.deflate";
const MODELS_DEV_CATALOG_RULES_JSON: &str = "src/models-dev-catalog-rules.json";
const OUT_MODELS_DEV_CATALOG_RULES_JSON: &str = "models-dev-catalog-rules.json.deflate";
const PRICING_JSON_PATH_ENV: &str = "CCUSAGE_PRICING_JSON_PATH";
#[cfg(feature = "fetch-litellm-pricing")]
const PRICING_FETCH_TIMEOUT_SECONDS: u64 = 10;
fn main() {
println!("cargo:rerun-if-env-changed={PRICING_JSON_PATH_ENV}");
let out_path = out_dir_path(OUT_PRICING_JSON);
let pricing_json = if let Some(path) = env::var_os(PRICING_JSON_PATH_ENV) {
let path = PathBuf::from(path);
println!("cargo:rerun-if-changed={}", path.display());
fs::read_to_string(path).expect("read pricing snapshot from CCUSAGE_PRICING_JSON_PATH")
} else {
println!("cargo:rerun-if-changed={FLAKE_LOCK_JSON}");
fetch_pricing_json()
};
let pricing_json = compact_pricing_json(&pricing_json).expect("compact LiteLLM pricing JSON");
fs::write(out_path, deflate(pricing_json.as_bytes()))
.expect("write build-time pricing snapshot");
embed_snapshot(MODELS_DEV_PRICING_JSON, OUT_MODELS_DEV_PRICING_JSON);
embed_snapshot(
MODELS_DEV_CATALOG_RULES_JSON,
OUT_MODELS_DEV_CATALOG_RULES_JSON,
);
}
/// The committed snapshots stay indented so their regeneration diffs stay
/// reviewable, but they are embedded verbatim, so the indentation - and, atView on GitHub (pinned to afebc5d2e0)
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.
Example fix
// before export CCUSAGE_PRICING_JSON_PATH=./litellm_prices.json # file not there // after export CCUSAGE_PRICING_JSON_PATH="$PWD/artifacts/litellm_prices.json" ls -l "$CCUSAGE_PRICING_JSON_PATH" && cargo build
Defensive patterns
Strategy: validation
Validate before calling
[ -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)"
Try / catch
let pricing_json = match env::var_os(PRICING_JSON_PATH_ENV) {
Some(p) => fs::read_to_string(PathBuf::from(&p))
.unwrap_or_else(|e| panic!("read pricing snapshot from {PRICING_JSON_PATH_ENV}={}: {e}", p.to_string_lossy())),
None => fetch_pricing_json(),
}; Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- write build-time pricing snapshot
- write generated CLI help
- unsupported pricing URL: {url}
- read CLI command spec
- compact LiteLLM pricing JSON
AI-assisted analysis of ccusage/ccusage@afebc5d2e0 (2026-09-02).
Data as JSON: /api/errors/cdd3166ea4e3043f.
Report an issue: GitHub.