a-b-street/abstreet · warning · anyhow::Error

missing from local storage

Error message

{} missing from local storage

What it means

read_local_storage returns this error when storage.get_item(&path) succeeds but yields None, i.e. the requested key does not exist in localStorage. The message includes the path so the developer knows which key was missing. This is the normal 'not found' outcome of the localStorage API surfaced as an anyhow error.

Solutions

  1. Use maybe_read_binary / handle the Err to supply a default value on first run
  2. Seed localStorage (or write defaults) before reading
  3. Verify the exact key path matches what write_raw/write_binary stored
  4. Persist important data server-side or in IndexedDB instead of localStorage to survive storage clears

Example fix

// before
let raw = abstio::slurp_file(path).unwrap(); // panics on first run
// after
let raw = abstio::maybe_read_binary(path).unwrap_or_else(|| default_bytes());
Defensive patterns

Strategy: fallback

Validate before calling

// check existence before reading
let exists = web_sys::window().unwrap()
    .local_storage().unwrap().unwrap()
    .get_item(path).unwrap().is_some();

Try / catch

let raw = slurp_file(path).unwrap_or_else(|_| default_contents());

Prevention

When it happens

Trigger: Calling abstio::slurp_file or maybe_read_binary for a path that was never written to localStorage on this origin/browser profile, or after the user cleared site data; also when the key name casing/format differs from what write_raw stored.

Common situations: First run of the app before any save; user cleared browser storage; reading a key written under a different path prefix/version; data lost because localStorage is per-origin and per-browser-profile.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/d5cfed0498a57cc6. Report an issue: GitHub.

Appendix: source

Thrown at abstio/src/io_web.rs:178

    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 success
pub fn write_file(path: String, contents: String) -> Result<String> {
    // Make the browser prompt the user to save a local file with arbitrary contents.
    use wasm_bindgen::JsCast;

View on GitHub (pinned to 0964f29315)