Hmbown/CodeWhale · error · anyhow::Error

DSH receipt has schema_version (this build understands )

Error message

DSH receipt {} has schema_version {} (this build understands {})

What it means

The DSH receipt file on disk declares a `schema_version` newer than RECEIPT_SCHEMA_VERSION, i.e. it was written by a newer build of codewhale. The loader refuses to parse/upgrade it to avoid data loss or misinterpretation, wrapping the failure in a parse-context error for the file path.

Solutions

  1. Upgrade codewhale to the version that wrote the receipt
  2. Back up the receipt file and delete it, then re-run the DSH connect flow to recreate it at the current schema
  3. Avoid mixing codewhale versions against the same workspace

Example fix

// before
codewhale-0.9 dsh connect   # writes schema_version 2
// after
cargo build # ensure binary >= version that wrote the receipt, then retry
Defensive patterns

Strategy: try-catch

Validate before calling

let raw = std::fs::read_to_string(&receipt_path)?;
let v: serde_json::Value = serde_json::from_str(&raw)?;
if v["schema_version"].as_u64().unwrap_or(0) > RECEIPT_SCHEMA_VERSION { /* upgrade binary or recreate */ }

Try / catch

match DshReceiptDocument::load(&path) { Err(e) if e.to_string().contains("schema_version") => { backup_and_recreate_receipt(); }, Err(e) => return Err(e.into()), doc => doc }

Prevention

When it happens

Trigger: Loading the DSH receipt (DshReceiptDocument::load) after downgrading the binary, switching branches, or sharing a receipt written by a newer codewhale version where doc.schema_version > RECEIPT_SCHEMA_VERSION.

Common situations: Rolling back codewhale after an upgrade; multiple codewhale builds of different versions pointed at the same workspace/config directory; restoring a receipt backup from a newer install.

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/9a3cafc02f90e63c. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/integrations/dsh/receipt.rs:121

impl Default for DshReceiptDocument {
    fn default() -> Self {
        Self {
            schema_version: RECEIPT_SCHEMA_VERSION,
            current: None,
            history: Vec::new(),
        }
    }
}

impl DshReceiptDocument {
    pub(crate) fn load(path: &Path) -> Result<Self> {
        match std::fs::read(path) {
            Ok(bytes) => {
                let doc: Self = serde_json::from_slice(&bytes)
                    .with_context(|| format!("parse DSH receipt {}", path.display()))?;
                if doc.schema_version > RECEIPT_SCHEMA_VERSION {
                    anyhow::bail!(
                        "DSH receipt {} has schema_version {} (this build understands {})",
                        path.display(),
                        doc.schema_version,
                        RECEIPT_SCHEMA_VERSION
                    );
                }
                Ok(doc)
            }
            Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(Self::default()),
            Err(error) => {
                Err(error).with_context(|| format!("read DSH receipt {}", path.display()))
            }
        }
    }

    pub(crate) fn push(&mut self, entry: DshReceiptEntry) {
        self.history.push(entry);
        if self.history.len() > MAX_HISTORY {

View on GitHub (pinned to 73e0f67d83)