{"record":{"id":"3508795c8dd1e835","repo":"sinelaw/fresh","slug":"invalid-calibration-file","errorCode":null,"errorMessage":"Invalid calibration file: {}","messagePattern":"Invalid calibration file: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/fresh-editor/src/input/key_translator.rs","lineNumber":267,"sourceCode":"    }\n\n    /// Clear all translations\n    pub fn clear(&mut self) {\n        self.translations.clear();\n    }\n\n    /// Load translations from a JSON file\n    ///\n    /// Returns an empty translator if the file doesn't exist.\n    /// Returns an error if the file exists but is invalid.\n    pub fn load_from_file(path: &Path) -> Result<Self, std::io::Error> {\n        if !path.exists() {\n            return Ok(Self::new());\n        }\n\n        let content = std::fs::read_to_string(path)?;\n        let file: CalibrationFile = serde_json::from_str(&content).map_err(|e| {\n            std::io::Error::new(\n                std::io::ErrorKind::InvalidData,\n                format!(\"Invalid calibration file: {}\", e),\n            )\n        })?;\n\n        let mut translator = Self::new();\n        for entry in file.translations {\n            translator.translations.insert(entry.raw, entry.expected);\n        }\n\n        tracing::info!(\n            \"Loaded {} key translations from {}\",\n            translator.len(),\n            path.display()\n        );\n\n        Ok(translator)\n    }","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-editor/src/input/key_translator.rs#L249-L285","documentation":"load_from_file reads a key calibration JSON file and deserializes it into CalibrationFile. If the JSON is present but fails serde parsing (wrong shape, unknown/missing fields, invalid values), it returns io::ErrorKind::InvalidData with 'Invalid calibration file: {serde error}'. A missing file is fine (defaults are used); only malformed content triggers this.","triggerScenarios":"Calling KeyTranslator::load_from_file(path) where path exists but contains invalid JSON, fields with wrong types, or a structure that does not match the current CalibrationFile schema (e.g. a file written by a different version).","commonSituations":"Hand-edited calibration file with a typo; calibration file written by an older/newer editor version whose schema changed; truncated or corrupted file after a crash during write.","solutions":["Validate/fix the JSON in the calibration file (run it through a JSON linter and compare against the CalibrationFile schema)","Regenerate the calibration file (delete it — load_from_file falls back to Self::new() defaults when the file is absent)","Check for a version mismatch: move the old file aside and let the current version recreate it","Wrap loading so parse failure degrades to defaults with a logged warning"],"exampleFix":"// before\nlet translator = KeyTranslator::load_from_file(&path)?; // hard error on bad JSON\n// after\nlet translator = KeyTranslator::load_from_file(&path).unwrap_or_else(|e| {\n    log::warn!(\"calibration unusable ({e}); using defaults\");\n    KeyTranslator::new()\n});","handlingStrategy":"fallback","validationCode":"fn calibration_file_ok(path: &Path) -> bool {\n    std::fs::read_to_string(path).ok()\n        .and_then(|c| serde_json::from_str::<serde_json::Value>(&c).ok())\n        .map(|v| v.get(\"version\").is_some())\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"let translator = KeyTranslator::load_from_file(path)\n    .or_else(|e| { log::warn!(\"calibration invalid: {e}\"); Ok(KeyTranslator::new()) })?;","preventionTips":["Write calibration files atomically (temp file + rename) to avoid truncation","Include a schema/version field and migrate on mismatch","Version-control or back up hand-edited calibration files"],"tags":["json","validation","config-file","keybinding"],"backgroundTag":"schema-validation-failed","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}