zed-industries/zed · error

Expected file_finder to be an object

Error message

Expected file_finder to be an object

What it means

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.

Source

Thrown at crates/migrator/src/migrations/m_2025_10_17/settings.rs:16

use anyhow::Result;
use serde_json::Value;

use crate::migrations::migrate_settings;

pub fn make_file_finder_include_ignored_an_enum(value: &mut Value) -> Result<()> {
    migrate_settings(value, &mut migrate_one)
}

fn migrate_one(obj: &mut serde_json::Map<String, Value>) -> Result<()> {
    let Some(file_finder) = obj.get_mut("file_finder") else {
        return Ok(());
    };

    let Some(file_finder_obj) = file_finder.as_object_mut() else {
        anyhow::bail!("Expected file_finder to be an object");
    };

    let Some(include_ignored) = file_finder_obj.get_mut("include_ignored") else {
        return Ok(());
    };
    *include_ignored = match include_ignored {
        Value::Bool(true) => Value::String("all".to_string()),
        Value::Bool(false) => Value::String("indexed".to_string()),
        Value::Null => Value::String("smart".to_string()),
        Value::String(s) if s == "all" || s == "indexed" || s == "smart" => return Ok(()),
        _ => anyhow::bail!("Expected include_ignored to be a boolean or null"),
    };
    Ok(())
}

View on GitHub (pinned to f4178619ac)

Solutions

  1. Open settings.json and wrap the value in an object: "file_finder": { ... }
  2. If you only meant the old include_ignored behavior, use "file_finder": { "include_ignored": "all" | "indexed" | "smart" }
  3. Remove the invalid `file_finder` key to fall back to defaults, then restart Zed

Example fix

// before
"file_finder": true

// after
"file_finder": { "include_ignored": "smart" }
Defensive patterns

Strategy: validation

Validate before calling

fn file_finder_shape_ok(value: &serde_json::Value) -> bool {
    value.get("file_finder").map_or(true, |ff| ff.is_object())
}

Type guard

fn is_file_finder_object(value: &serde_json::Value) -> bool {
    value.get("file_finder").map_or(true, serde_json::Value::is_object)
}

Try / catch

if let Err(err) = migrate_settings(&mut settings, &mut migrate_one) {
    if err.to_string().contains("file_finder") {
        // strip or repair the file_finder key, then re-run
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20). Data as JSON: /api/errors/750c9f7eb7b212cb. Report an issue: GitHub.