{"record":{"id":"6f3d062f7d4a0a63","repo":"zed-industries/zed","slug":"expected-include-ignored-to-be-a-boolean-or-null","errorCode":null,"errorMessage":"Expected include_ignored to be a boolean or null","messagePattern":"Expected include_ignored to be a boolean or null","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/migrator/src/migrations/m_2025_10_17/settings.rs","lineNumber":27,"sourceCode":"\nfn migrate_one(obj: &mut serde_json::Map<String, Value>) -> Result<()> {\n    let Some(file_finder) = obj.get_mut(\"file_finder\") else {\n        return Ok(());\n    };\n\n    let Some(file_finder_obj) = file_finder.as_object_mut() else {\n        anyhow::bail!(\"Expected file_finder to be an object\");\n    };\n\n    let Some(include_ignored) = file_finder_obj.get_mut(\"include_ignored\") else {\n        return Ok(());\n    };\n    *include_ignored = match include_ignored {\n        Value::Bool(true) => Value::String(\"all\".to_string()),\n        Value::Bool(false) => Value::String(\"indexed\".to_string()),\n        Value::Null => Value::String(\"smart\".to_string()),\n        Value::String(s) if s == \"all\" || s == \"indexed\" || s == \"smart\" => return Ok(()),\n        _ => anyhow::bail!(\"Expected include_ignored to be a boolean or null\"),\n    };\n    Ok(())\n}\n","sourceCodeStart":9,"sourceCodeEnd":31,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/migrator/src/migrations/m_2025_10_17/settings.rs#L9-L31","documentation":"Same m_2025_10_17 migration, one level deeper: after `file_finder` is confirmed to be an object, `include_ignored` is remapped (true→\"all\", false→\"indexed\", null→\"smart\", existing all/indexed/smart strings pass through). Any other value — a number, an array, or an unrecognized string like \"everything\" — hits the catch-all arm and bails.","triggerScenarios":"settings.json has \"file_finder\": { \"include_ignored\": 1 } or \"include_ignored\": \"everything\"; the key being absent is fine, only present-but-unrecognized values fail.","commonSituations":"Typos in the enum value; users guessing a string value before the schema was widely documented; scripts writing raw numbers into the field.","solutions":["Set include_ignored to one of the accepted strings: \"all\", \"indexed\", or \"smart\"","Or restore the boolean form (true/false) and let the migration convert it on next start","Remove the key to accept the default (\"smart\")"],"exampleFix":"// before\n\"file_finder\": { \"include_ignored\": \"everything\" }\n\n// after\n\"file_finder\": { \"include_ignored\": \"all\" }","handlingStrategy":"validation","validationCode":"const VALID: [&str; 3] = [\"all\", \"indexed\", \"smart\"];\nfn include_ignored_ok(value: &serde_json::Value) -> bool {\n    value\n        .pointer(\"/file_finder/include_ignored\")\n        .map_or(true, |v| {\n            v.is_boolean() || v.is_null()\n                || v.as_str().map_or(false, |s| VALID.contains(&s))\n        })\n}","typeGuard":"fn is_valid_include_ignored(v: &serde_json::Value) -> bool {\n    matches!(v, serde_json::Value::Bool(_))\n        || v.is_null()\n        || v.as_str().map_or(false, |s| matches!(s, \"all\" | \"indexed\" | \"smart\"))\n}","tryCatchPattern":"match migrate_one(&mut obj) {\n    Err(e) if e.to_string().contains(\"include_ignored\") => {\n        obj.get_mut(\"file_finder\").unwrap().as_object_mut().unwrap().remove(\"include_ignored\");\n    }\n    r => r?,\n}","preventionTips":["Spell the enum exactly: all / indexed / smart","Treat booleans and null as the only legacy forms; never numbers","After settings-sync tools run, spot-check enum keys for corruption"],"tags":["zed","settings","migration","file-finder","enum"],"backgroundTag":"settings-schema-validation-failed","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}