zed-industries/zed · error
unrecognized serialized thread version: {version:?}
Error message
unrecognized serialized thread version: {version:?} What it means
`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.
Source
Thrown at crates/agent/src/legacy_thread.rs:66
pub model: String,
}
impl SerializedThread {
pub const VERSION: &'static str = "0.2.0";
pub fn from_json(json: &[u8]) -> Result<Self> {
let saved_thread_json = serde_json::from_slice::<serde_json::Value>(json)?;
match saved_thread_json.get("version") {
Some(serde_json::Value::String(version)) => match version.as_str() {
SerializedThreadV0_1_0::VERSION => {
let saved_thread =
serde_json::from_value::<SerializedThreadV0_1_0>(saved_thread_json)?;
Ok(saved_thread.upgrade())
}
SerializedThread::VERSION => Ok(serde_json::from_value::<SerializedThread>(
saved_thread_json,
)?),
_ => anyhow::bail!("unrecognized serialized thread version: {version:?}"),
},
None => {
let saved_thread =
serde_json::from_value::<LegacySerializedThread>(saved_thread_json)?;
Ok(saved_thread.upgrade())
}
version => anyhow::bail!("unrecognized serialized thread version: {version:?}"),
}
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct SerializedThreadV0_1_0(
// The structure did not change, so we are reusing the latest SerializedThread.
// When making the next version, make sure this points to SerializedThreadV0_2_0
SerializedThread,
);
View on GitHub (pinned to f4178619ac)
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.
Example fix
// crates/agent/src/legacy_thread.rs — adding a new schema version
// before
match version.as_str() {
SerializedThreadV0_1_0::VERSION => { /* upgrade */ }
SerializedThread::VERSION => { /* parse */ }
_ => anyhow::bail!("unrecognized serialized thread version: {version:?}"),
}
// after
match version.as_str() {
SerializedThreadV0_1_0::VERSION => { /* upgrade */ }
SerializedThreadV0_2_0::VERSION => { /* upgrade */ }
SerializedThread::VERSION => { /* parse */ }
_ => anyhow::bail!("unrecognized serialized thread version: {version:?}"),
} Defensive patterns
Strategy: validation
Validate before calling
// Inspect the version before deserializing:
let value: serde_json::Value = serde_json::from_slice(json)?;
const KNOWN: &[&str] = &[SerializedThreadV0_1_0::VERSION, SerializedThread::VERSION];
match value.get("version") {
Some(serde_json::Value::String(v)) if KNOWN.contains(&v.as_str()) => { /* safe to call from_json */ }
_ => { /* unknown version — migrate or reject with a clear message */ }
} Type guard
fn known_thread_version(value: &serde_json::Value) -> bool {
matches!(value.get("version"), Some(serde_json::Value::String(v))
if v == SerializedThreadV0_1_0::VERSION || v == SerializedThread::VERSION)
} Try / catch
match SerializedThread::from_json(&bytes) {
Err(e) if e.to_string().contains("unrecognized serialized thread version") => {
// skip this record; report version to the user instead of failing the whole load
}
rest => rest,
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Cannot list directory because its path matches the user's wo
- Cannot list directory because its path matches the user's wo
- Path not found: {}
- {} is not a directory.
- Cannot read file because its path matches the global `file_s
AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20).
Data as JSON: /api/errors/9272a4beb60cd938.
Report an issue: GitHub.