{"record":{"id":"750c9f7eb7b212cb","repo":"zed-industries/zed","slug":"expected-file-finder-to-be-an-object","errorCode":null,"errorMessage":"Expected file_finder to be an object","messagePattern":"Expected file_finder to be an object","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/migrator/src/migrations/m_2025_10_17/settings.rs","lineNumber":16,"sourceCode":"use anyhow::Result;\nuse serde_json::Value;\n\nuse crate::migrations::migrate_settings;\n\npub fn make_file_finder_include_ignored_an_enum(value: &mut Value) -> Result<()> {\n    migrate_settings(value, &mut migrate_one)\n}\n\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":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/migrator/src/migrations/m_2025_10_17/settings.rs#L1-L31","documentation":"Thrown by the m_2025_10_17 settings migration, which converts `file_finder.include_ignored` from a boolean to the string enum all/indexed/smart. It first requires the `file_finder` key itself to be a JSON object; a string, number, boolean, or array in its place cannot be migrated and the migration aborts.","triggerScenarios":"settings.json contains \"file_finder\": \"project\" (or true, 3, [...]) instead of an object, and Zed's startup migration runs. Note: `file_finder` being absent is fine; only a present-but-non-object value fails.","commonSituations":"Users abbreviating the setting as a string; copied config snippets that predate the object shape; a stray value left by find/replace edits in settings.json.","solutions":["Open settings.json and wrap the value in an object: \"file_finder\": { ... }","If you only meant the old include_ignored behavior, use \"file_finder\": { \"include_ignored\": \"all\" | \"indexed\" | \"smart\" }","Remove the invalid `file_finder` key to fall back to defaults, then restart Zed"],"exampleFix":"// before\n\"file_finder\": true\n\n// after\n\"file_finder\": { \"include_ignored\": \"smart\" }","handlingStrategy":"validation","validationCode":"fn file_finder_shape_ok(value: &serde_json::Value) -> bool {\n    value.get(\"file_finder\").map_or(true, |ff| ff.is_object())\n}","typeGuard":"fn is_file_finder_object(value: &serde_json::Value) -> bool {\n    value.get(\"file_finder\").map_or(true, serde_json::Value::is_object)\n}","tryCatchPattern":"if let Err(err) = migrate_settings(&mut settings, &mut migrate_one) {\n    if err.to_string().contains(\"file_finder\") {\n        // strip or repair the file_finder key, then re-run\n    }\n}","preventionTips":["Model file_finder as an object in snippets you share/save","Validate settings shape after automated edits or settings sync","When a setting becomes an enum-in-object, update dotfile templates accordingly"],"tags":["zed","settings","migration","file-finder","json-schema"],"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"}