a-b-street/abstreet · error

Can't find the data/ directory

Error message

Can't find the data/ directory

What it means

abstio::path resolves non-player paths by locating the repo's data/ directory: it checks ABST_DATA_DIR (compile time), wasm, then data/, ../data/, ../../data/, ../../../data/ relative to the current working directory. If none of these exists when the path root is first initialized, it panics with 'Can't find the data/ directory'. This is the player/-branch variant (ROOT_PLAYER_DIR), i.e. it fires while resolving a 'player/...' path.

Solutions

  1. Run the binary from a directory where data/ exists (the repo root) or within 3 levels of it (so ../data, ../../data, or ../../../data resolves)
  2. Rebuild with ABST_DATA_DIR set to the absolute path of the data directory: ABST_DATA_DIR=/path/to/abstreet/data cargo build --release
  3. Clone/sync the data directory (e.g. ./import.sh or downloading data from the project) next to where the binary runs
  4. Patch ROOT_PLAYER_DIR resolution to accept an explicit runtime override (env var read at runtime instead of option_env!)

Example fix

// before
./target/release/abstreet   # run from ~/, no data/ nearby -> panic
// after
cd /path/to/abstreet && ./target/release/abstreet
# or: ABST_DATA_DIR=/path/to/abstreet/data cargo build --release
Defensive patterns

Strategy: validation

Validate before calling

fn data_dir_locatable() -> bool {
    ["data/", "../data/", "../../data/", "../../../data/"]
        .iter()
        .any(|p| std::path::Path::new(p).is_dir())
        || std::env::var_os("ABST_DATA_DIR").is_some()
}

Type guard

fn can_resolve_abstio_paths() -> bool {
    cfg!(target_arch = "wasm32")
        || std::env::var_os("ABST_DATA_DIR").is_some()
        || data_dir_locatable()
}

Try / catch

let ok = std::panic::catch_unwind(|| abstio::path("system/us/seattle/maps/montlake.bin"));
if ok.is_err() {
    eprintln!("Run from the repo root (or set ABST_DATA_DIR at build time)");
}

Prevention

When it happens

Trigger: First call to abstio::path (or path_player/path_edits/path_save etc.) with a 'player/'-prefixed path, from a working directory where none of data/, ../data/, ../../data/, ../../../data/ exists and the binary was not compiled with ABST_DATA_DIR set (or not on wasm32). The OnceLock caches the failure on the first call.

Common situations: Running a compiled A/B Street binary outside the repository checkout (e.g. copying the executable elsewhere), running tests/crates from a directory above or beside the repo, CI jobs that don't clone data/, or builds without ABST_DATA_DIR set while packaged.

Related errors


AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/f86f41344843b931. Report an issue: GitHub.

Appendix: source

Thrown at abstio/src/abst_paths.rs:41

            // If you're packaging for a release and want the player's local data directory to be
            // $HOME/.abstreet, set ABST_PLAYER_HOME_DIR=1
            if option_env!("ABST_PLAYER_HOME_DIR").is_some() {
                match std::env::var("HOME") {
                    Ok(dir) => format!("{}/.abstreet", dir.trim_end_matches('/')),
                    Err(err) => panic!("This build of A/B Street stores player data in $HOME/.abstreet, but $HOME isn't set: {}", err),
                }
            } else if cfg!(target_arch = "wasm32") {
                "../data".to_string()
            } else if file_exists("data/".to_string()) {
                "data".to_string()
            } else if file_exists("../data/".to_string()) {
                "../data".to_string()
            } else if file_exists("../../data/".to_string()) {
                "../../data".to_string()
            } else if file_exists("../../../data/".to_string()) {
                "../../../data".to_string()
            } else {
                panic!("Can't find the data/ directory");
            }
        });
        format!("{dir}/{p}")
    } else {
        let dir = ROOT_DIR.get_or_init(|| {
            // If you're packaging for a release and need the data directory to be in some fixed
            // location: ABST_DATA_DIR=/some/path cargo build ...
            if let Some(dir) = option_env!("ABST_DATA_DIR") {
                dir.trim_end_matches('/').to_string()
            } else if cfg!(target_arch = "wasm32") {
                "../data".to_string()
            } else if file_exists("data/".to_string()) {
                "data".to_string()
            } else if file_exists("../data/".to_string()) {
                "../data".to_string()
            } else if file_exists("../../data/".to_string()) {
                "../../data".to_string()
            } else if file_exists("../../../data/".to_string()) {

View on GitHub (pinned to 0964f29315)