{"record":{"id":"0f5722b05b9a35f9","repo":"Hmbown/CodeWhale","slug":"runtime-turn-operation-binding-schema-v-is-newer-than","errorCode":null,"errorMessage":"Runtime turn operation binding schema v{} is newer than supported v{}","messagePattern":"Runtime turn operation binding schema v(.+?) is newer than supported v(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_threads.rs","lineNumber":3466,"sourceCode":"        .map(parse_runtime_reasoning_effort)\n        .transpose()\n        .map(|effort| effort.map(|effort| effort.as_setting().to_string()))\n}\n\n#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]\nstruct RuntimeTurnOperationBinding {\n    schema_version: u32,\n    thread_id: String,\n    turn_id: String,\n    operation_key_fingerprint: String,\n    request_fingerprint: String,\n    created_at: DateTime<Utc>,\n}\n\nimpl RuntimeTurnOperationBinding {\n    fn validate(&self) -> Result<()> {\n        if self.schema_version > TURN_OPERATION_BINDING_SCHEMA_VERSION {\n            bail!(\n                \"Runtime turn operation binding schema v{} is newer than supported v{}\",\n                self.schema_version,\n                TURN_OPERATION_BINDING_SCHEMA_VERSION\n            );\n        }\n        validated_record_id(&self.thread_id, \"operation thread id\")?;\n        validated_record_id(&self.turn_id, \"operation turn id\")?;\n        validate_sha256_fingerprint(&self.operation_key_fingerprint, \"operation key fingerprint\")?;\n        validate_sha256_fingerprint(&self.request_fingerprint, \"operation request fingerprint\")?;\n        Ok(())\n    }\n}\n\n#[derive(Debug, Clone)]\nstruct PreparedRuntimeTurnOperation {\n    binding: RuntimeTurnOperationBinding,\n    requested_turn_id: Option<String>,\n}","sourceCodeStart":3448,"sourceCodeEnd":3484,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/runtime_threads.rs#L3448-L3484","documentation":"RuntimeTurnOperationBinding::validate compares the binding record's schema_version to TURN_OPERATION_BINDING_SCHEMA_VERSION (currently 1). A binding stamped by a newer binary is refused, along with further checks on thread id and other fields. This keeps claim/lock metadata interpretable by the running process.","triggerScenarios":"Validating a persisted turn-operation binding (claim/lock file) whose schema_version is greater than TURN_OPERATION_BINDING_SCHEMA_VERSION — i.e., the file was written by a newer release that bumped the binding schema.","commonSituations":"Downgrading Codewhale while leftover binding files from a newer version remain in the store; two versions of the app sharing one runtime directory; a crash left a binding that the old binary cannot validate.","solutions":["Upgrade to the newer build that wrote the binding.","Delete the stale binding file once no process owns the turn operation, then retry the claim.","Use one runtime store directory per app version.","Check schema_version in the binding JSON; a value of 1 or less with this error indicates a different problem (corrupt file) to investigate separately."],"exampleFix":"// before: stale binding blocks startup\n$ rm ~/.local/share/codewhale/runtime/turn-bindings/<op-id>.json\n\n// after (programmatic)\nmatch binding {\n    Ok(b) => use_binding(b),\n    Err(e) if e.to_string().contains(\"newer than supported\") => {\n        remove_stale_binding(&path)?; // only if no live owner\n        retry_claim(key)?;\n    }\n    Err(e) => return Err(e),\n}","handlingStrategy":"try-catch","validationCode":"let v: serde_json::Value = serde_json::from_str(&std::fs::read_to_string(&binding_path)?)?;\nif v[\"schema_version\"].as_u64().unwrap_or(1) > TURN_OPERATION_BINDING_SCHEMA_VERSION as u64 {\n    eprintln!(\"binding written by newer build; remove only if no live owner\");\n}","typeGuard":"fn binding_supported(b: &RuntimeTurnOperationBinding) -> bool {\n    b.schema_version <= TURN_OPERATION_BINDING_SCHEMA_VERSION\n}","tryCatchPattern":"match binding.validate() {\n    Ok(()) => proceed(binding),\n    Err(e) if e.to_string().contains(\"newer than supported\") => {\n        if !owner_alive(&binding) { remove(&path)?; retry_claim(key)?; }\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Remove leftover bindings only after confirming the owning process is dead.","Avoid sharing one runtime directory between different app versions.","Upgrade before resuming sessions created by a newer build."],"tags":["schema","versioning","locking"],"backgroundTag":"schema-version-mismatch","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}