a-b-street/abstreet · error · anyhow::Error
no local_storage?
Error message
no local_storage?
What it means
read_local_storage expects window.local_storage() to return Some(Storage); a None means the browser gave no storage object for this origin. The library turns that into the "no local_storage?" error. This is separate from a failed call or a missing key.
Solutions
- Treat localStorage as optional: fall back to in-memory or IndexedDB storage
- Detect the condition up front with web_sys::window().and_then(|w| w.local_storage().ok().flatten()) before using the library API
- Enable storage for the webview/origin in the embedding application
- Inform the user that saving requires enabling site data
Example fix
// before
let raw = abstio::slurp_file(path).expect("storage");
// after
let has_storage = web_sys::window()
.and_then(|w| w.local_storage().ok().flatten())
.is_some();
let raw = if has_storage { abstio::slurp_file(path)? } else { default_value() }; Defensive patterns
Strategy: fallback
Validate before calling
let has_storage = web_sys::window()
.and_then(|w| w.local_storage().ok().flatten())
.is_some(); Type guard
fn local_storage_available() -> bool {
web_sys::window().and_then(|w| w.local_storage().ok().flatten()).is_some()
} Try / catch
let raw = if local_storage_available() {
slurp_file(path).unwrap_or_default()
} else {
in_memory_store().get(path).cloned().unwrap_or_default()
}; Prevention
- Treat localStorage as optional and pick a backend at startup
- Enable WebStorage in embedded webview configurations
- Test in private-browsing modes where storage may be absent
- Cache data in memory so a missing Storage object degrades gracefully
When it happens
Trigger: Calling read_local_storage (via slurp_file/maybe_read_binary) in a context where window.local_storage() resolves to None — e.g. storage disabled for the origin, certain privacy modes, or insecure/embedded contexts where the browser suppresses localStorage.
Common situations: Safari older private-browsing sessions where localStorage appears absent; embedded webviews with WebStorage disabled; origins with storage partitioned away.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- no window?
- local_storage failed
- get_item failed
- set_item for failed for encoded length
- missing from local storage
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/0af740c9de42fc0c.
Report an issue: GitHub.
Appendix: source
Thrown at abstio/src/io_web.rs:174
if !path.starts_with(&path_player("")) {
warn!("Not deleting {}", path);
return;
}
let window = web_sys::window().unwrap();
let storage = window.local_storage().unwrap().unwrap();
storage.remove_item(path).unwrap();
}
fn read_local_storage(path: &str) -> Result<String> {
let window = web_sys::window().ok_or(anyhow!("no window?"))?;
let storage = window
.local_storage()
.map_err(|err| {
anyhow!(err
.as_string()
.unwrap_or("local_storage failed".to_string()))
})?
.ok_or(anyhow!("no local_storage?"))?;
let string = storage
.get_item(&path)
.map_err(|err| anyhow!(err.as_string().unwrap_or("get_item failed".to_string())))?
.ok_or(anyhow!("{} missing from local storage", path))?;
Ok(string)
}
fn list_local_storage_keys() -> Vec<String> {
let window = web_sys::window().unwrap();
let storage = window.local_storage().unwrap().unwrap();
let mut keys = Vec::new();
for idx in 0..storage.length().unwrap() {
keys.push(storage.key(idx).unwrap().unwrap());
}
keys
}
/// Returns path on successView on GitHub (pinned to 0964f29315)