a-b-street/abstreet · critical

Can't read

Error message

Can't read {}: {}

What it means

slurp_bytes resolves a filename via the crate's environment-aware path() lookup and reads the whole file into memory. If slurp_file returns an error (missing file, permission denied, IO error), it panics with "Can't read {path}: {err}". This is an intentional abort: the caller asked for an asset the library assumes must exist (e.g. an SVG read by widgetry's settings).

Solutions

  1. Verify the file exists at the resolved path (abstio::path(filename) plus std::path::Path::exists) before calling slurp_bytes.
  2. Run the binary from the repo root or set the correct data directory so relative asset paths resolve.
  3. Use abstio::slurp_file with Result handling (or maybe_slurp) if a missing file is an expected, recoverable condition instead of slurp_bytes.
  4. Check file permissions and that packaging/deploy includes the asset files.

Example fix

// before
let bytes = abstio::slurp_bytes("icons/pin.svg");
// after
let path = abstio::path("icons/pin.svg");
if !std::path::Path::new(&path).exists() {
    eprintln!("missing asset {}", path);
    return;
}
let bytes = abstio::slurp_bytes("icons/pin.svg");
Defensive patterns

Strategy: validation

Validate before calling

let path = abstio::path("icons/pin.svg");
assert!(std::path::Path::new(&path).exists(), "missing asset: {}", path);

Try / catch

// panics; cannot catch in Rust. Pre-check instead:
match abstio::slurp_file(&abstio::path(name)) {
    Ok(bytes) => use(bytes),
    Err(e) => eprintln!("skipping {}: {}", name, e),
}

Prevention

When it happens

Trigger: Calling abstio::slurp_bytes(filename) where path(filename) does not exist, is unreadable (permissions), or the underlying read fails with an IO error. Common with SVG assets passed to widgetry::Settings::read_svg.

Common situations: Running the app from the wrong working directory so relative asset paths don't resolve; a missing/misnamed SVG resource; deployment packaging that omitted asset files; permission-restricted data directories.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at abstio/src/lib.rs:39

#[cfg(not(target_arch = "wasm32"))]
mod download;
#[cfg(not(target_arch = "wasm32"))]
pub use download::*;

pub use abst_data::*;
pub use abst_paths::*;
pub use http::*;

mod abst_data;
mod abst_paths;
mod http;
mod io;

/// An adapter for widgetry::Settings::read_svg to read SVGs using this crate's methods for finding
/// and reading files in different environments.
pub fn slurp_bytes(filename: &str) -> Vec<u8> {
    let path = path(filename);
    slurp_file(&path).unwrap_or_else(|err| panic!("Can't read {}: {}", path, err))
}

View on GitHub (pinned to 0964f29315)