{"record":{"id":"9272a4beb60cd938","repo":"zed-industries/zed","slug":"unrecognized-serialized-thread-version-version","errorCode":null,"errorMessage":"unrecognized serialized thread version: {version:?}","messagePattern":"unrecognized serialized thread version: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/agent/src/legacy_thread.rs","lineNumber":66,"sourceCode":"    pub model: String,\n}\n\nimpl SerializedThread {\n    pub const VERSION: &'static str = \"0.2.0\";\n\n    pub fn from_json(json: &[u8]) -> Result<Self> {\n        let saved_thread_json = serde_json::from_slice::<serde_json::Value>(json)?;\n        match saved_thread_json.get(\"version\") {\n            Some(serde_json::Value::String(version)) => match version.as_str() {\n                SerializedThreadV0_1_0::VERSION => {\n                    let saved_thread =\n                        serde_json::from_value::<SerializedThreadV0_1_0>(saved_thread_json)?;\n                    Ok(saved_thread.upgrade())\n                }\n                SerializedThread::VERSION => Ok(serde_json::from_value::<SerializedThread>(\n                    saved_thread_json,\n                )?),\n                _ => anyhow::bail!(\"unrecognized serialized thread version: {version:?}\"),\n            },\n            None => {\n                let saved_thread =\n                    serde_json::from_value::<LegacySerializedThread>(saved_thread_json)?;\n                Ok(saved_thread.upgrade())\n            }\n            version => anyhow::bail!(\"unrecognized serialized thread version: {version:?}\"),\n        }\n    }\n}\n\n#[derive(Serialize, Deserialize, Debug)]\npub struct SerializedThreadV0_1_0(\n    // The structure did not change, so we are reusing the latest SerializedThread.\n    // When making the next version, make sure this points to SerializedThreadV0_2_0\n    SerializedThread,\n);\n","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/agent/src/legacy_thread.rs#L48-L84","documentation":"`SerializedThread::from_json` reads the `version` field of a saved agent thread and dispatches on it: `\"0.1.0\"` upgrades via `SerializedThreadV0_1_0`, `\"0.2.0\"` (`SerializedThread::VERSION`) parses directly, and any other string bails here. It means the JSON is a thread store from a Zed build whose schema version this code does not know.","triggerScenarios":"Loading a thread JSON written by a newer Zed (version `\"0.3.0\"`+), a hand-edited `version` string, or a file that is not a thread document but happens to contain a `version` string field.","commonSituations":"Downgrading Zed after threads were saved by a newer version; opening a thread DB from another machine running newer Zed; schema-version constants drifting between forks/branches of the codebase.","solutions":["Reopen the thread with the Zed version that wrote it and export/complete it there.","Upgrade Zed to at least the version that produced the file.","If the version was hand-edited, restore the original `\"0.1.0\"`/`\"0.2.0\"` value — but only if the body really matches that schema.","As a developer adding a schema bump, register the new constant in the `match` in `legacy_thread.rs::from_json` and add an upgrade path."],"exampleFix":"// crates/agent/src/legacy_thread.rs — adding a new schema version\n// before\nmatch version.as_str() {\n    SerializedThreadV0_1_0::VERSION => { /* upgrade */ }\n    SerializedThread::VERSION => { /* parse */ }\n    _ => anyhow::bail!(\"unrecognized serialized thread version: {version:?}\"),\n}\n// after\nmatch version.as_str() {\n    SerializedThreadV0_1_0::VERSION => { /* upgrade */ }\n    SerializedThreadV0_2_0::VERSION => { /* upgrade */ }\n    SerializedThread::VERSION => { /* parse */ }\n    _ => anyhow::bail!(\"unrecognized serialized thread version: {version:?}\"),\n}","handlingStrategy":"validation","validationCode":"// Inspect the version before deserializing:\nlet value: serde_json::Value = serde_json::from_slice(json)?;\nconst KNOWN: &[&str] = &[SerializedThreadV0_1_0::VERSION, SerializedThread::VERSION];\nmatch value.get(\"version\") {\n    Some(serde_json::Value::String(v)) if KNOWN.contains(&v.as_str()) => { /* safe to call from_json */ }\n    _ => { /* unknown version — migrate or reject with a clear message */ }\n}","typeGuard":"fn known_thread_version(value: &serde_json::Value) -> bool {\n    matches!(value.get(\"version\"), Some(serde_json::Value::String(v))\n        if v == SerializedThreadV0_1_0::VERSION || v == SerializedThread::VERSION)\n}","tryCatchPattern":"match SerializedThread::from_json(&bytes) {\n    Err(e) if e.to_string().contains(\"unrecognized serialized thread version\") => {\n        // skip this record; report version to the user instead of failing the whole load\n    }\n    rest => rest,\n}","preventionTips":["Never hand-edit the `version` field of saved threads.","When bumping the schema, extend the version match in `from_json` and add an upgrade arm in the same commit.","Pin the writing and reading code to the same Zed version during rollouts."],"tags":["rust","zed","agent","serialization","version-mismatch","thread-history"],"backgroundTag":"serialization-version-mismatch","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}