{"record":{"id":"fa87f3666be6d1e0","repo":"a-b-street/abstreet","slug":"couldn-t-read-object","errorCode":null,"errorMessage":"Couldn't read_object({}): {}","messagePattern":"Couldn't read_object\\((.+?)\\): (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"abstio/src/io.rs","lineNumber":50,"sourceCode":"        Ok(obj) => obj,\n        Err(err) => panic!(\"Couldn't read_binary({}): {}\", path, err),\n    }\n}\n\n/// May be a JSON or binary file\npub fn read_object<T: DeserializeOwned>(path: String, timer: &mut Timer) -> Result<T> {\n    if path.ends_with(\".bin\") {\n        maybe_read_binary(path, timer)\n    } else {\n        maybe_read_json(path, timer)\n    }\n}\n\n/// May be a JSON or binary file. Panics on failure.\npub fn must_read_object<T: DeserializeOwned>(path: String, timer: &mut Timer) -> T {\n    match read_object(path.clone(), timer) {\n        Ok(obj) => obj,\n        Err(err) => panic!(\"Couldn't read_object({}): {}\", path, err),\n    }\n}\n\n/// Keeps file extensions\npub fn find_prev_file(orig: String) -> Option<String> {\n    let mut files = list_dir(parent_path(&orig));\n    files.reverse();\n    files.into_iter().find(|f| *f < orig)\n}\n\npub fn find_next_file(orig: String) -> Option<String> {\n    let files = list_dir(parent_path(&orig));\n    files.into_iter().find(|f| *f > orig)\n}\n\n/// Load all serialized things from a directory, return sorted by name, with file extension removed.\n/// Detects JSON or binary. Filters out broken files.\npub fn load_all_objects<T: DeserializeOwned>(dir: String) -> Vec<(String, T)> {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/abstio/src/io.rs#L32-L68","documentation":"must_read_object loads a file that may be JSON or bincode (dispatched by the .bin extension via read_object) and panics with this message if reading or deserialization fails. It is the infallible wrapper around read_object, which returns Result. The panic indicates the path is missing/unreadable, or the contents don't parse into T.","triggerScenarios":"Calling must_read_object(path, timer) with a nonexistent or unreadable path; a JSON file with invalid JSON; a .bin file with invalid/mismatched bincode data; a path lacking .json/.geojson (read_json bails) or malformed contents; type T not matching the file's schema.","commonSituations":"Typos in data paths or wrong working directory; input datasets edited by hand and broken; schema drift after upgrading the crate's types so old JSON/bincode files no longer deserialize; forgetting the .json extension so maybe_read_json bails.","solutions":["Confirm the file exists at the exact path (abstio::file_exists) and has the right extension (.json/.geojson or .bin).","Validate the file's JSON parses (e.g. serde_json::from_str in isolation) or regenerate the .bin file.","Use read_object and match on the Err to recover or skip the file, as load_all_objects does.","If types changed between versions, migrate or re-export the input files with the current schema."],"exampleFix":"// before\nlet obj = abstio::must_read_object::<Config>(path.clone(), &mut timer);\n\n// after\nlet obj = match abstio::read_object::<Config>(path.clone(), &mut timer) {\n    Ok(o) => o,\n    Err(err) => {\n        eprintln!(\"Couldn't read {}: {}\", path, err);\n        Config::default()\n    }\n};","handlingStrategy":"fallback","validationCode":"if !abstio::file_exists(&path)\n    || !(path.ends_with(\".json\") || path.ends_with(\".geojson\") || path.ends_with(\".bin\")) {\n    eprintln!(\"{} missing or has wrong extension\", path);\n}","typeGuard":"fn is_readable_object_path(path: &str) -> bool {\n    let p = std::path::Path::new(path);\n    p.is_file()\n        && (path.ends_with(\".json\") || path.ends_with(\".geojson\") || path.ends_with(\".bin\"))\n}","tryCatchPattern":"match abstio::read_object::<T>(path.clone(), &mut timer) {\n    Ok(obj) => obj,\n    Err(err) => { eprintln!(\"read_object({}) failed: {}\", path, err); Default::default() }\n}","preventionTips":["Use read_object (Result) instead of must_read_object when inputs are user-supplied or optional.","Keep input files' extensions consistent (.json/.geojson or .bin) with their actual encoding.","Re-export or migrate input datasets after schema changes between versions.","Validate hand-edited JSON inputs before feeding them to the library."],"tags":["rust","panic","deserialization","file-io"],"backgroundTag":"file-read-failed","analyzedSha":"0964f29315820c91b171b585eb51e300164e9197","analyzedAt":"2026-09-13T18:02:03.421Z","contentChangedAt":"2026-09-13T18:02:03.421Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}