{"record":{"id":"6c9523effb0dc72f","repo":"Hmbown/CodeWhale","slug":"trigger-schema-v-is-newer-than-supported-v","errorCode":null,"errorMessage":"Trigger schema v{} is newer than supported v{}","messagePattern":"Trigger schema v(.+?) is newer than supported v(.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/automation_manager.rs","lineNumber":1365,"sourceCode":"            fired_at: None,\n            task_id: None,\n            thread_id: None,\n            error: None,\n            parent_trigger_id: req.parent_trigger_id,\n        };\n        self.save_trigger(&record)?;\n        Ok(record)\n    }\n\n    /// Load a trigger by id.\n    pub fn get_trigger(&self, trigger_id: &str) -> Result<DelayedTriggerRecord> {\n        let path = self.trigger_path(trigger_id)?;\n        let raw = fs::read_to_string(&path)\n            .with_context(|| format!(\"Trigger '{trigger_id}' not found\"))?;\n        let record: DelayedTriggerRecord = serde_json::from_str(&raw)\n            .with_context(|| format!(\"Failed to parse trigger '{trigger_id}'\"))?;\n        if record.schema_version > CURRENT_TRIGGER_SCHEMA_VERSION {\n            bail!(\n                \"Trigger schema v{} is newer than supported v{}\",\n                record.schema_version,\n                CURRENT_TRIGGER_SCHEMA_VERSION\n            );\n        }\n        Ok(record)\n    }\n\n    /// Load a trigger only when it belongs to the given session.\n    ///\n    /// Foreign, ownerless legacy, unreadable, and absent records share the same\n    /// result so trigger existence cannot be disclosed across sessions.\n    pub fn get_trigger_for_owner(\n        &self,\n        trigger_id: &str,\n        owner_session_id: &str,\n    ) -> Result<DelayedTriggerRecord> {\n        self.get_trigger(trigger_id)","sourceCodeStart":1347,"sourceCodeEnd":1383,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/automation_manager.rs#L1347-L1383","documentation":"Thrown by AutomationManager::get_trigger when a persisted DelayedTriggerRecord under ~/.codewhale/automations/triggers/{trigger_id}.json declares a schema_version greater than CURRENT_TRIGGER_SCHEMA_VERSION (v1 in this build). Every trigger record is stamped with the schema version of the binary that wrote it, and this guard makes an older codewhale fail fast instead of misreading fields a newer release added or renamed. The message reports the on-disk version first and the highest supported version second.","triggerScenarios":"Calling get_trigger (directly or via get_trigger_for_owner, cancel_trigger_for_owner, collect_due_triggers, or trigger listings) on a trigger JSON file whose schema_version field exceeds the compiled constant — i.e. a record written by a newer codewhale release that bumped the trigger schema.","commonSituations":"Downgrading codewhale after a newer version scheduled delayed triggers; copying or syncing ~/.codewhale from a machine running a newer build; running a beta channel that wrote newer-schema records and then reverting to stable.","solutions":["Upgrade codewhale to at least the version that wrote the record (the first version number in the message is the on-disk schema).","If you must stay on the older build, archive or delete the offending file at ~/.codewhale/automations/triggers/{trigger_id}.json; that pending continuation will be lost.","Use a separate state directory per codewhale version so an older binary never reads records from a newer one."],"exampleFix":"// before\nlet record = manager.get_trigger(trigger_id)?;\n\n// after: surface an upgrade hint instead of a raw load failure\nlet record = match manager.get_trigger(trigger_id) {\n    Ok(record) => record,\n    Err(err) if err.to_string().contains(\"newer than supported\") => {\n        anyhow::bail!(\"trigger '{trigger_id}' was written by a newer codewhale; upgrade or remove its JSON file\")\n    }\n    Err(err) => return Err(err),\n};","handlingStrategy":"try-catch","validationCode":"fn trigger_schema_readable(path: &std::path::Path, supported: u32) -> bool {\n    std::fs::read(path)\n        .ok()\n        .and_then(|raw| serde_json::from_slice::<serde_json::Value>(&raw).ok())\n        .map(|v| v[\"schema_version\"].as_u64().unwrap_or(0) <= supported as u64)\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"Match the anyhow error on the \"newer than supported\" substring: report an upgrade instruction (or skip the record in listings) instead of retrying; propagate every other load error unchanged.","preventionTips":["Keep one codewhale version per state directory.","Do not downgrade below the newest version that has run against a shared ~/.codewhale.","Before bulk-importing trigger archives, inspect their schema_version fields."],"tags":["rust","schema-version","persistence","automation","backward-compatibility"],"backgroundTag":"schema-version-mismatch","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}