zed-industries/zed · error

The `code_action` is in an invalid state and cannot be migra

Error message

The `code_action` is in an invalid state and cannot be migrated at {}. Please ensure the code_action setting is a String

What it means

Thrown by Zed's settings migrator (m_2025_10_16) while converting the legacy formatter `code_action` entries into the new `code_actions` map. For every element of a `formatter` array it expects `code_action` to be a JSON string naming a formatter (e.g. "prettier"); any other JSON type (object, number, bool, array, null) cannot be mapped, so the whole settings migration aborts and the message names the offending settings file path.

Source

Thrown at crates/migrator/src/migrations/m_2025_10_16/settings.rs:49

    let Some(formatter) = obj.get("formatter") else {
        return Ok(());
    };
    let formatter_array = if let Some(array) = formatter.as_array() {
        array.clone()
    } else {
        vec![formatter.clone()]
    };
    if formatter_array.is_empty() {
        return Ok(());
    }
    let mut code_action_formatters = Vec::new();
    for formatter in formatter_array {
        let Some(code_action) = formatter.get("code_action") else {
            return Ok(());
        };
        let Some(code_action_name) = code_action.as_str() else {
            anyhow::bail!(
                r#"The `code_action` is in an invalid state and cannot be migrated at {}. Please ensure the code_action setting is a String"#,
                fmt_path(path, "formatter"),
            );
        };
        code_action_formatters.push(code_action_name.to_string());
    }

    code_actions_map.extend(
        code_action_formatters
            .into_iter()
            .rev()
            .map(|code_action| (code_action, Value::Bool(true))),
    );

    obj.insert("formatter".to_string(), Value::Array(vec![]));
    obj.insert(
        "code_actions_on_format".into(),
        Value::Object(code_actions_map),

View on GitHub (pinned to f4178619ac)

Solutions

  1. Open the settings file named in the error (the path is printed at the `formatter` key) and change the value to a plain string, e.g. "code_action": "prettier"
  2. Remove the malformed `code_action` key entirely if no code-action formatter is wanted for that entry
  3. Search every settings layer (user settings, project settings, language entries, profiles) for `code_action` and fix all non-string occurrences, then restart so migrations re-run

Example fix

// before
"formatter": [{ "code_action": { "name": "prettier" } }]

// after
"formatter": [{ "code_action": "prettier" }]
Defensive patterns

Strategy: validation

Validate before calling

fn formatter_entries_valid(value: &serde_json::Value) -> bool {
    value.get("formatter").map_or(true, |f| {
        f.as_array().map_or(false, |entries| {
            entries.iter().all(|e| {
                e.get("code_action").map_or(true, |ca| ca.is_string())
            })
        })
    })
}

Type guard

fn is_string_code_action(entry: &serde_json::Value) -> bool {
    entry.get("code_action").map_or(true, |ca| ca.is_string())
}

Try / catch

match migrate(value) {
    Err(err) if err.to_string().contains("code_action") => {
        eprintln!("fix the formatter code_action entry named in: {err}");
    }
    rest => rest?,
}

Prevention

When it happens

Trigger: A settings.json (user, project, or language entry) contains "formatter": [{ "code_action": { ... } }] or a number/boolean instead of a string, and Zed runs its startup settings migrations (or the migrator crate is invoked directly on that file).

Common situations: Hand-editing settings.json and nesting formatter options under code_action; pasting snippets from outdated docs or AI answers that model code_action as a structured value; an extension or profile writing a non-string value into a formatter entry.

Related errors


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