a-b-street/abstreet · warning
Not saving
Error message
Not saving {} What it means
abstio::write_raw on web only persists paths under the player data directory (localStorage); writing anywhere else is refused with "Not saving {path}". This is intentional: web builds cannot write to the real filesystem, so arbitrary paths are rejected rather than silently dropped.
Solutions
- On web, write only to paths under the player data directory.
- For user-facing exports, use the download-style API (write_file) which triggers a browser download instead.
- Gate saving code paths with cfg(not(target_arch = "wasm32")) or check the target before attempting the write.
Example fix
// before
abstio::write_binary("../data/player/settings.bin", &settings);
// after
#[cfg(target_arch = "wasm32")]
abstio::write_file("settings.bin", abstutil::to_binary(&settings));
#[cfg(not(target_arch = "wasm32"))]
abstio::write_binary("../data/player/settings.bin", &settings); Defensive patterns
Strategy: validation
Validate before calling
fn can_persist_on_web(path: &str) -> bool { path.starts_with("../data/player/") } Try / catch
if abstio::write_raw(path, bytes).is_err() {
log::warn!("web build cannot save {} - skipping", path);
} Prevention
- Only write under data/player/ in web builds.
- Use write_file for downloads; write_raw only for player persistence.
- Compile-time gate file writes with cfg(not(target_arch = "wasm32")).
When it happens
Trigger: Calling write_raw / write_binary with a path outside data/player/ on the web target — e.g. saving maps, settings, or recordings to data/system or other native-only locations.
Common situations: Porting native code that writes arbitrary output files to web; attempting to export large files expecting a real download; assuming symmetric read/write support on web.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Can't slurp_file , it doesn't exist
- Can't maybe_read_binary
- Don't know MIME type for
- Unsupported on web
- Don't know how to load
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/db95bd91965caf4a.
Report an issue: GitHub.
Appendix: source
Thrown at abstio/src/io_web.rs:137
// Only save for data/player, for now
if !path.starts_with(&path_player("")) {
warn!("Not saving {}", path);
return;
}
let window = web_sys::window().unwrap();
let storage = window.local_storage().unwrap().unwrap();
storage.set_item(&path, &abstutil::to_json(obj)).unwrap();
}
pub fn write_binary<T: Serialize>(path: String, obj: &T) {
write_raw(path, &abstutil::to_binary(obj)).unwrap();
}
pub fn write_raw(path: String, bytes: &[u8]) -> Result<()> {
// Only save for data/player, for now
if !path.starts_with(&path_player("")) {
bail!("Not saving {}", path);
}
let window = web_sys::window().unwrap();
let storage = window.local_storage().unwrap().unwrap();
// Local storage only supports strings, so base64 encoding needed
use base64::Engine;
let encoded = base64::engine::general_purpose::STANDARD.encode(bytes);
storage.set_item(&path, &encoded).map_err(|err| {
anyhow!(err.as_string().unwrap_or_else(|| format!(
"set_item for {path} failed for encoded length {}",
encoded.len()
)))
})?;
Ok(())
}
pub fn delete_file<I: AsRef<str>>(path: I) {
let path = path.as_ref();View on GitHub (pinned to 0964f29315)