a-b-street/abstreet · error
Couldn't read_object
Error message
Couldn't read_object({}): {} What it means
must_read_object loads a file that may be JSON or bincode (dispatched by the .bin extension via read_object) and panics with this message if reading or deserialization fails. It is the infallible wrapper around read_object, which returns Result. The panic indicates the path is missing/unreadable, or the contents don't parse into T.
Solutions
- Confirm the file exists at the exact path (abstio::file_exists) and has the right extension (.json/.geojson or .bin).
- Validate the file's JSON parses (e.g. serde_json::from_str in isolation) or regenerate the .bin file.
- Use read_object and match on the Err to recover or skip the file, as load_all_objects does.
- If types changed between versions, migrate or re-export the input files with the current schema.
Example fix
// before
let obj = abstio::must_read_object::<Config>(path.clone(), &mut timer);
// after
let obj = match abstio::read_object::<Config>(path.clone(), &mut timer) {
Ok(o) => o,
Err(err) => {
eprintln!("Couldn't read {}: {}", path, err);
Config::default()
}
}; Defensive patterns
Strategy: fallback
Validate before calling
if !abstio::file_exists(&path)
|| !(path.ends_with(".json") || path.ends_with(".geojson") || path.ends_with(".bin")) {
eprintln!("{} missing or has wrong extension", path);
} Type guard
fn is_readable_object_path(path: &str) -> bool {
let p = std::path::Path::new(path);
p.is_file()
&& (path.ends_with(".json") || path.ends_with(".geojson") || path.ends_with(".bin"))
} Try / catch
match abstio::read_object::<T>(path.clone(), &mut timer) {
Ok(obj) => obj,
Err(err) => { eprintln!("read_object({}) failed: {}", path, err); Default::default() }
} Prevention
- Use read_object (Result) instead of must_read_object when inputs are user-supplied or optional.
- Keep input files' extensions consistent (.json/.geojson or .bin) with their actual encoding.
- Re-export or migrate input datasets after schema changes between versions.
- Validate hand-edited JSON inputs before feeding them to the library.
When it happens
Trigger: Calling must_read_object(path, timer) with a nonexistent or unreadable path; a JSON file with invalid JSON; a .bin file with invalid/mismatched bincode data; a path lacking .json/.geojson (read_json bails) or malformed contents; type T not matching the file's schema.
Common situations: Typos in data paths or wrong working directory; input datasets edited by hand and broken; schema drift after upgrading the crate's types so old JSON/bincode files no longer deserialize; forgetting the .json extension so maybe_read_json bails.
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
- Couldn't read_json( )
- Couldn't read_binary
- Can't write_json( )
- Can't write_binary( )
- Compressed not there?
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/fa87f3666be6d1e0.
Report an issue: GitHub.
Appendix: source
Thrown at abstio/src/io.rs:50
Ok(obj) => obj,
Err(err) => panic!("Couldn't read_binary({}): {}", path, err),
}
}
/// May be a JSON or binary file
pub fn read_object<T: DeserializeOwned>(path: String, timer: &mut Timer) -> Result<T> {
if path.ends_with(".bin") {
maybe_read_binary(path, timer)
} else {
maybe_read_json(path, timer)
}
}
/// May be a JSON or binary file. Panics on failure.
pub fn must_read_object<T: DeserializeOwned>(path: String, timer: &mut Timer) -> T {
match read_object(path.clone(), timer) {
Ok(obj) => obj,
Err(err) => panic!("Couldn't read_object({}): {}", path, err),
}
}
/// Keeps file extensions
pub fn find_prev_file(orig: String) -> Option<String> {
let mut files = list_dir(parent_path(&orig));
files.reverse();
files.into_iter().find(|f| *f < orig)
}
pub fn find_next_file(orig: String) -> Option<String> {
let files = list_dir(parent_path(&orig));
files.into_iter().find(|f| *f > orig)
}
/// Load all serialized things from a directory, return sorted by name, with file extension removed.
/// Detects JSON or binary. Filters out broken files.
pub fn load_all_objects<T: DeserializeOwned>(dir: String) -> Vec<(String, T)> {View on GitHub (pinned to 0964f29315)