a-b-street/abstreet · error · anyhow::Error
local_storage failed
Error message
local_storage failed
What it means
read_local_storage maps a failure of window.local_storage() to the underlying exception's text, falling back to "local_storage failed" when the DomException has no message. This means the browser refused or failed the attempt to access the localStorage object itself. It is distinct from the key simply being missing.
Solutions
- Ask the user to enable cookies/site data / disable the blocking extension for the site
- Avoid sandboxed iframes or add allow-same-origin to the sandbox attribute
- Log the underlying exception message (err.as_string()) to diagnose which exception occurred
- Fall back to in-memory storage or IndexedDB when localStorage is unavailable
Example fix
// before
let raw = abstio::slurp_file(path).unwrap();
// after
let raw = abstio::slurp_file(path).unwrap_or_else(|e| {
warn!("localStorage unavailable ({e}); using defaults");
String::new()
}); Defensive patterns
Strategy: try-catch
Validate before calling
let storage_ok = web_sys::window()
.and_then(|w| w.local_storage().ok())
.transpose()
.is_ok(); Try / catch
match slurp_file(path) {
Ok(v) => v,
Err(e) => { log::warn!("storage access failed: {e}"); Default::default() }
} Prevention
- Handle localStorage-unavailable environments gracefully (private mode, blockers)
- Test with browser privacy settings that block site data
- Avoid sandboxed iframes without allow-same-origin
- Always provide an in-memory or network fallback for reads
When it happens
Trigger: Calling read_local_storage (via slurp_file/maybe_read_binary) when window.local_storage() returns Err — e.g. cookies/site-data blocked, storage access denied by browser privacy settings, or the page opened in a context where storage is disabled (some private-browsing modes in older browsers).
Common situations: Users with strict privacy settings or extensions blocking storage; sandboxed iframes without allow-same-origin; embedded webviews with storage disabled.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- no window?
- no local_storage?
- 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/d1c6619cedcb216f.
Report an issue: GitHub.
Appendix: source
Thrown at abstio/src/io_web.rs:170
}
pub fn delete_file<I: AsRef<str>>(path: I) {
let path = path.as_ref();
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());
}View on GitHub (pinned to 0964f29315)