Hmbown/CodeWhale · error

Turn schema v is newer than supported v

Error message

Turn schema v{} is newer than supported v{}

What it means

`TurnRecord::validate_output_token_limit` refuses to load a turn record whose `schema_version` exceeds `MAX_SUPPORTED_RUNTIME_SCHEMA_VERSION`. This is a forward-compatibility guard: a newer binary must not silently misinterpret fields written by a newer schema.

Solutions

  1. Upgrade the application to a build supporting the record's schema version.
  2. Move the newer turn records out of the data directory if staying on the old build.
  3. Discard or archive the too-new turn record if its data is not needed.
Defensive patterns

Strategy: try-catch

Validate before calling

const MAX_SCHEMA: u32 = MAX_SUPPORTED_RUNTIME_SCHEMA_VERSION;
if record.schema_version > MAX_SCHEMA { return Err(format!("schema v{} too new (max v{})", record.schema_version, MAX_SCHEMA)); }

Try / catch

match store.load_turn(&turn_id) { Err(e) if e.contains("newer than supported") => { archive_record(&turn_id); warn_and_skip() }, Err(e) => Err(e.into()), Ok(t) => Ok(t) }

Prevention

When it happens

Trigger: Loading a turn file written by a newer Codewhale build (higher schema version) with an older binary; downgrading the app and opening existing thread data.

Common situations: Rolling back a release; sharing thread data between machines running different versions; a preview build wrote records a stable build cannot read.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/e2932b225607023d. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/runtime_threads.rs:1045

    )]
    pub model_request_diagnostics: Option<RuntimeTurnRequestDiagnostics>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error: Option<String>,
    #[serde(default)]
    pub item_ids: Vec<String>,
    #[serde(default)]
    pub steer_count: usize,
    /// Stable Agent Mail id that caused this turn. This is the durable
    /// idempotency bridge between a claimed mail envelope and the existing
    /// turn queue; ordinary external-user turns leave it unset.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub agent_mail_message_id: Option<String>,
}

impl TurnRecord {
    fn validate_output_token_limit(&self) -> Result<()> {
        if self.schema_version > MAX_SUPPORTED_RUNTIME_SCHEMA_VERSION {
            bail!(
                "Turn schema v{} is newer than supported v{}",
                self.schema_version,
                MAX_SUPPORTED_RUNTIME_SCHEMA_VERSION
            );
        }
        if self.max_output_tokens.is_some()
            != (self.schema_version == OUTPUT_LIMIT_RUNTIME_SCHEMA_VERSION)
        {
            bail!("Turn output allowance does not match its schema");
        }
        Ok(())
    }

    pub(crate) fn effective_provider_label(&self) -> Option<&str> {
        self.effective_provider_id
            .as_deref()
            .filter(|identity| !identity.trim().is_empty())
            .or_else(|| {

View on GitHub (pinned to 73e0f67d83)