{"record":{"id":"8167deb75708e00d","repo":"zed-industries/zed","slug":"error-fallible-options","errorCode":null,"errorMessage":"{error}","messagePattern":"\\{error\\}","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/settings_content/src/fallible_options.rs","lineNumber":161,"sourceCode":"{\n    match object.remove(key) {\n        None => Ok(T::default()),\n        Some(value) => T::deserialize(&value),\n    }\n}\n\npub(crate) fn section<T>(rest: &serde_json::Value) -> Result<T, serde_json::Error>\nwhere\n    T: serde::de::DeserializeOwned,\n{\n    T::deserialize(rest)\n}\n\n#[inline(never)]\nfn recover_deserialization_error(recover: &mut dyn FnMut(&mut dyn FnMut(&dyn Display))) {\n    ERRORS.with_borrow_mut(|errors| {\n        if let Some(errors) = errors {\n            recover(&mut |error| errors.push(anyhow::anyhow!(\"{error}\")));\n        }\n    });\n}\n\n#[cfg(test)]\nmod tests {\n    use serde::Deserialize;\n    use settings_macros::with_fallible_options;\n\n    use crate::ParseStatus;\n\n    #[with_fallible_options]\n    #[derive(Deserialize, Debug, PartialEq)]\n    struct Foo {\n        foo: Option<String>,\n        bar: Option<usize>,\n        baz: Option<bool>,\n    }","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/zed-industries/zed/blob/916fc2b8cb3a815cbef4a3b40e13081be72036b6/crates/settings_content/src/fallible_options.rs#L143-L179","documentation":"fallible_options deserialization parses settings values leniently: recover_deserialization_error collects each deserialization problem reported by serde into a thread-local ERRORS list as anyhow errors, so parsing can continue and all issues be reported at once. This entry is the error created per offending value — meaning one or more settings fields in the user's settings file had values that could not be deserialized into the expected option types.","triggerScenarios":"Deserializing a settings file (via deserialize → recover_deserialization_error) where a field expected as a fallible option (e.g. bool, number, enum) holds an incompatible value; serde's recover callback is invoked with the display of each failing field's error and it is pushed into the collected errors.","commonSituations":"Hand-edited settings.json with a mistyped value (\"true\" as string instead of boolean, wrong enum variant, nested object where scalar expected); settings written by an older Zed version whose schema has changed; copy-pasted config from documentation of a different version.","solutions":["Read the collected error messages — each names the offending settings key and expected type — and correct those values in settings.json.","Check for schema changes after upgrading: compare the settings keys against the current defaults/documentation for the installed version.","Remove the offending key entirely to fall back to the default value if you don't need it.","Validate the settings JSON types with a JSON schema/linter before saving."],"exampleFix":"// before (settings.json)\n{ \"buffer_font_size\": \"14\" }\n// after\n{ \"buffer_font_size\": 14 }","handlingStrategy":"validation","validationCode":"// pre-validate the settings value types before deserialization\nfn check_setting(key: &str, value: &serde_json::Value, expected: &str) -> bool {\n    let ok = match expected {\n        \"bool\" => value.is_boolean(),\n        \"number\" => value.is_number(),\n        \"string\" => value.is_string(),\n        _ => true,\n    };\n    if !ok { eprintln!(\"{key}: expected {expected}, got {value}\"); }\n    ok\n}","typeGuard":null,"tryCatchPattern":"match SettingsContent::deserialize(&value) {\n    Ok(content) => apply(content),\n    Err(e) => {\n        for err in collected_errors() { // fallible_options collects each bad field\n            eprintln!(\"settings issue: {err:#}\");\n        }\n        apply_defaults();\n    }\n}","preventionTips":["Edit settings with schema-aware validation (JSON schema / editor integration) enabled","After upgrading, review settings keys that changed type or variants in the release notes","Quote-free scalars: never wrap booleans/numbers in strings in settings.json","Delete unknown or suspect keys to fall back to defaults rather than guessing values"],"tags":["settings","deserialization","config","serde","schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"916fc2b8cb3a815cbef4a3b40e13081be72036b6","analyzedAt":"2026-09-19T19:09:50.599Z","contentChangedAt":"2026-09-19T19:09:50.599Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}