{"record":{"id":"2f5231f4be9bd84d","repo":"zed-industries/zed","slug":"expected-relative-line-numbers-to-be-a-boolean","errorCode":null,"errorMessage":"Expected relative_line_numbers to be a boolean","messagePattern":"Expected relative_line_numbers to be a boolean","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/migrator/src/migrations/m_2025_10_21/settings.rs","lineNumber":19,"sourceCode":"use anyhow::Result;\nuse serde_json::Value;\n\nuse crate::migrations::migrate_settings;\n\npub fn make_relative_line_numbers_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(relative_line_numbers) = obj.get_mut(\"relative_line_numbers\") else {\n        return Ok(());\n    };\n\n    *relative_line_numbers = match relative_line_numbers {\n        Value::Bool(true) => Value::String(\"enabled\".to_string()),\n        Value::Bool(false) => Value::String(\"disabled\".to_string()),\n        Value::String(s) if s == \"enabled\" || s == \"disabled\" || s == \"wrapped\" => return Ok(()),\n        _ => anyhow::bail!(\"Expected relative_line_numbers to be a boolean\"),\n    };\n    Ok(())\n}\n","sourceCodeStart":1,"sourceCodeEnd":23,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/migrator/src/migrations/m_2025_10_21/settings.rs#L1-L23","documentation":"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.","triggerScenarios":"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.","commonSituations":"Muscle-memory editors writing 1/0 for booleans; guessing \"on\"/\"off\" as the enum; stale third-party settings sync tools writing arbitrary values.","solutions":["Set the value to a valid string: \"enabled\", \"disabled\", or \"wrapped\"","Or use a boolean (true/false) and let the migration convert it once","Remove the key to use the default"],"exampleFix":"// before\n\"relative_line_numbers\": \"on\"\n\n// after\n\"relative_line_numbers\": \"enabled\"","handlingStrategy":"validation","validationCode":"const VALID: [&str; 3] = [\"enabled\", \"disabled\", \"wrapped\"];\nfn relative_line_numbers_ok(value: &serde_json::Value) -> bool {\n    value.get(\"relative_line_numbers\").map_or(true, |v| {\n        v.is_boolean() || v.as_str().map_or(false, |s| VALID.contains(&s))\n    })\n}","typeGuard":"fn is_valid_relative_line_numbers(v: &serde_json::Value) -> bool {\n    v.is_boolean()\n        || v.as_str().map_or(false, |s| matches!(s, \"enabled\" | \"disabled\" | \"wrapped\"))\n}","tryCatchPattern":"if err.to_string().contains(\"relative_line_numbers\") {\n    // rewrite the key to \"enabled\"/\"disabled\" or delete it, then re-run migration\n}","preventionTips":["Use only true/false or the three enum strings for this key","Don't approximate booleans with 1/0 in JSON settings","Re-read the setting docs after Zed upgrades that rename types"],"tags":["zed","settings","migration","line-numbers","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"}