a-b-street/abstreet · error
Couldn't read
Error message
Couldn't read {} What it means
The default Settings::read_svg closure panics when the SVG file at the given path cannot be opened (fs_err::File::open fails). It reports "Couldn't read {path}" — typically the file doesn't exist or isn't readable at the time an asset is loaded.
Solutions
- Verify the path exists relative to the process's current working directory.
- Fix the asset path/filename spelling and case.
- Ship the asset with the application and reference it correctly in packaging.
- Override Settings.read_svg with include_bytes!-based embedding or a custom loader returning empty bytes/own error handling.
Example fix
// before
let mut file = fs_err::File::open(path).unwrap_or_else(|_| panic!("Couldn't read {}", path));
// after
let mut file = fs_err::File::open(path).unwrap_or_else(|e| panic!("Couldn't read {}: {}", path, e)); Defensive patterns
Strategy: validation
Validate before calling
if !std::path::Path::new(path).exists() { eprintln!("missing asset: {}", path); }
// or at startup, probe all assets:
// for p in REQUIRED_SVGS { assert!(Path::new(p).exists(), "missing asset {}", p); } Try / catch
// Provide a custom read_svg that returns empty bytes + logs instead of panicking:
settings.read_svg = Box::new(|path| std::fs::read(path).unwrap_or_else(|e| { log::error!("{}: {}", path, e); Vec::new() })); Prevention
- Embed assets with include_bytes! or a packaged resource dir
- Probe all required asset paths at startup with a clear error listing
- Use case-exact filenames for cross-platform builds
- Run from a known cwd or resolve asset paths relative to the executable
When it happens
Trigger: Calling load_svg with a path that doesn't exist on disk, a path relative to the wrong working directory, or a file without read permissions, while using the default read_svg implementation in Settings.
Common situations: Assets not packaged with the binary (missing from include dir or install bundle), running the app from a different cwd than during development, typos in asset filenames, Linux case-sensitivity vs Windows-authored paths.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/5734d64e4f84793e.
Report an issue: GitHub.
Appendix: source
Thrown at widgetry/src/runner.rs:227
/// Specify the title of the window to open.
pub fn new(window_title: &str) -> Settings {
Settings {
window_title: window_title.to_string(),
#[cfg(target_arch = "wasm32")]
root_dom_element_id: "widgetry-canvas".to_string(),
assets_base_url: None,
assets_are_gzipped: false,
dump_raw_events: false,
scale_factor: None,
require_minimum_width: None,
window_icon: None,
loading_tips: None,
load_default_textures: true,
read_svg: Box::new(|path| {
use std::io::Read;
let mut file =
fs_err::File::open(path).unwrap_or_else(|_| panic!("Couldn't read {}", path));
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)
.unwrap_or_else(|_| panic!("Couldn't read all of {}", path));
buffer
}),
canvas_settings: CanvasSettings::new(),
}
}
/// Log every raw winit event to the DEBUG level.
pub fn dump_raw_events(mut self) -> Self {
assert!(!self.dump_raw_events);
self.dump_raw_events = true;
self
}
/// Override the initial HiDPI scale factor from whatever winit initially detects.
pub fn scale_factor(mut self, scale_factor: f64) -> Self {View on GitHub (pinned to 0964f29315)