zed-industries/zed · error

Expected relative_line_numbers to be a boolean

Error message

Expected relative_line_numbers to be a boolean

What it means

The m_2025_10_21 migration converts the top-level `relative_line_numbers` boolean into the string enum enabled/disabled/wrapped. Booleans are remapped, and strings already equal to enabled/disabled/wrapped are left as-is; every other JSON value (number, object, array, or an unknown string) bails and blocks settings migration.

Source

Thrown at crates/migrator/src/migrations/m_2025_10_21/settings.rs:19

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

use crate::migrations::migrate_settings;

pub fn make_relative_line_numbers_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(relative_line_numbers) = obj.get_mut("relative_line_numbers") else {
        return Ok(());
    };

    *relative_line_numbers = match relative_line_numbers {
        Value::Bool(true) => Value::String("enabled".to_string()),
        Value::Bool(false) => Value::String("disabled".to_string()),
        Value::String(s) if s == "enabled" || s == "disabled" || s == "wrapped" => return Ok(()),
        _ => anyhow::bail!("Expected relative_line_numbers to be a boolean"),
    };
    Ok(())
}

View on GitHub (pinned to f4178619ac)

Solutions

  1. Set the value to a valid string: "enabled", "disabled", or "wrapped"
  2. Or use a boolean (true/false) and let the migration convert it once
  3. Remove the key to use the default

Example fix

// before
"relative_line_numbers": "on"

// after
"relative_line_numbers": "enabled"
Defensive patterns

Strategy: validation

Validate before calling

const VALID: [&str; 3] = ["enabled", "disabled", "wrapped"];
fn relative_line_numbers_ok(value: &serde_json::Value) -> bool {
    value.get("relative_line_numbers").map_or(true, |v| {
        v.is_boolean() || v.as_str().map_or(false, |s| VALID.contains(&s))
    })
}

Type guard

fn is_valid_relative_line_numbers(v: &serde_json::Value) -> bool {
    v.is_boolean()
        || v.as_str().map_or(false, |s| matches!(s, "enabled" | "disabled" | "wrapped"))
}

Try / catch

if err.to_string().contains("relative_line_numbers") {
    // rewrite the key to "enabled"/"disabled" or delete it, then re-run migration
}

Prevention

When it happens

Trigger: settings.json contains "relative_line_numbers": 1, "relative_line_numbers": "on", or any value outside {true, false, "enabled", "disabled", "wrapped"} when Zed starts and runs migrations.

Common situations: Muscle-memory editors writing 1/0 for booleans; guessing "on"/"off" as the enum; stale third-party settings sync tools writing arbitrary values.

Related errors


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