{"record":{"id":"836f210d7e3f7729","repo":"coding-horror/basic-computer-games","slug":"error-loading-stats-data","errorCode":null,"errorMessage":"Error loading stats data!","messagePattern":"Error loading stats data!","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"81_Splat/rust/src/stats.rs","lineNumber":78,"sourceCode":"        let mut placement = all_jumps;\n\n        for (i, altitude) in self.altitudes.iter().enumerate() {\n            if a <= *altitude {\n                placement = i + 1;\n                break;\n            }\n        }\n\n        utility::print_win(all_jumps, placement);\n\n        self.altitudes.push(a);\n        self.altitudes.sort_by(|a, b| a.partial_cmp(b).unwrap());\n\n        self.write();\n    }\n\n    fn write(&self) {\n        let mut file = File::create(\"src/stats.txt\").expect(\"Error loading stats data!\");\n\n        let mut altitudes = String::new();\n\n        for a in &self.altitudes {\n            altitudes.push_str(format!(\"{},\", a).as_str());\n        }\n\n        write!(&mut file, \"{}\", altitudes.trim()).expect(\"ERROR WRITING Stats FILE!\");\n    }\n}\n","sourceCodeStart":60,"sourceCodeEnd":89,"githubUrl":"https://github.com/coding-horror/basic-computer-games/blob/5301155192d91d74d337899cecc59dbda59c4c17/81_Splat/rust/src/stats.rs#L60-L89","documentation":"This panic is triggered by `.expect(\"Error loading stats data!\")` on `File::create(\"src/stats.txt\")` inside `Stats::write()` in Splat (line 78). The message is misleading — `write()` is *saving* data, not loading it. The panic fires when `File::create` fails on the hardcoded relative path `src/stats.txt`, typically because the `src/` directory does not exist relative to the current working directory.","triggerScenarios":"The binary is run from a directory where `src/stats.txt` cannot be created (missing `src/` parent, permissions, read-only FS). Since `write()` is called from `add_altitude()` after every successful jump, this panic can occur mid-gameplay after stats are already in memory.","commonSituations":"Running the compiled binary outside the project root (the `src/` directory only exists during development). Deploying the binary without the source tree. The binary is installed system-wide but the hardcoded relative path points nowhere. This means stats saving works during development but breaks in production.","solutions":["Use a proper data directory: `dirs::data_dir()` or a configurable path instead of the hardcoded `\"src/stats.txt\"`.","Create the parent directory with `create_dir_all` before `File::create`.","Replace `.expect` with error handling that logs the failure and degrades gracefully (skip the save, warn the user).","Fix the misleading message to reflect the actual operation (writing, not loading)."],"exampleFix":"// before\nfn write(&self) {\n    let mut file = File::create(\"src/stats.txt\").expect(\"Error loading stats data!\");\n    // ...\n}\n\n// after\nfn write(&self) {\n    let path = \"src/stats.txt\";\n    let mut file = match File::create(path) {\n        Ok(f) => f,\n        Err(e) => {\n            eprintln!(\"Warning: could not save stats: {}\", e);\n            return;\n        }\n    };\n    // ...\n}","handlingStrategy":"validation","validationCode":"// Validate path writability before the write() call\nuse std::path::Path;\nlet path = Path::new(\"src/stats.txt\");\nif let Some(parent) = path.parent() {\n    if !parent.exists() {\n        std::fs::create_dir_all(parent).ok();\n    }\n}","typeGuard":"fn can_write_stats() -> bool {\n    let path = \"src/stats.txt\";\n    let p = std::path::Path::new(path);\n    p.parent().map(|d| d.exists() || std::fs::create_dir_all(d).is_ok())\n        .unwrap_or(true)\n}","tryCatchPattern":"fn write(&self) {\n    let mut file = match File::create(\"src/stats.txt\") {\n        Ok(f) => f,\n        Err(e) => {\n            eprintln!(\"Warning: cannot save stats: {}\", e);\n            return;\n        }\n    };\n    // ...\n}","preventionTips":["Never hardcode relative paths to the source tree in a compiled binary.","Use dirs::data_dir() or a configurable path for runtime data files.","Create parent directories with create_dir_all before writing.","Log save failures and continue rather than crashing mid-game."],"tags":["rust","file-io","panic","expect","relative-path","misleading-message","hardcoded-path","splat","stats-persistence"],"backgroundTag":null,"analyzedSha":"5301155192d91d74d337899cecc59dbda59c4c17","analyzedAt":"2026-08-13T19:29:00.979Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}