BoundaryML/baml · error · Error

failed to decode {kind}: {message}

Error message

failed to decode {kind}: {message}

What it means

`Error::Decode` wraps a Borsh deserialization failure that occurred after the artifact envelope (magic, header, hash) validated successfully but the payload bytes could not be interpreted as the expected type `T`. The inner `message` describes the deserialization problem.

Source

Thrown at baml_language/crates/baml_artifact/src/lib.rs:146

        expected: ArtifactKind,
        actual: ArtifactKind,
    },
    #[error("{kind} artifact failed integrity validation")]
    InvalidPayloadHash { kind: ArtifactKind },
    #[error(
        "{kind}: toolchain {artifact_fingerprint} / format {artifact_format}; this runtime: {runtime_fingerprint} / format {runtime_format} — {remediation}"
    )]
    Incompatible {
        kind: ArtifactKind,
        artifact_fingerprint: String,
        artifact_format: u32,
        runtime_fingerprint: &'static str,
        runtime_format: u32,
        remediation: &'static str,
    },
    #[error("failed to encode {kind}: {message}")]
    Encode { kind: ArtifactKind, message: String },
    #[error("failed to decode {kind}: {message}")]
    Decode { kind: ArtifactKind, message: String },
}

/// Serialize `value` and wrap it in a versioned artifact envelope.
pub fn encode<T: BorshSerialize>(kind: ArtifactKind, value: &T) -> Result<Vec<u8>, Error> {
    let payload = borsh::to_vec(value).map_err(|error| Error::Encode {
        kind,
        message: error.to_string(),
    })?;
    encode_payload(kind, &payload)
}

/// Encode a value with an explicit artifact format for cross-crate skew tests.
#[cfg(feature = "test-support")]
#[doc(hidden)]
pub fn encode_with_format_for_test<T: BorshSerialize>(
    artifact_format: u32,
    kind: ArtifactKind,

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Regenerate the artifact with the toolchain matching the runtime so the payload schema matches the decode type.
  2. Check the inner `message` to find which field offsets/types diverge and align the Rust type with the writer's schema.
  3. Ensure the format-version constant is bumped whenever the serialized struct changes, so stale artifacts are rejected with Incompatible instead of Decode errors.
  4. Verify you are decoding with the same type `T` the artifact was encoded with.

Example fix

// before
let manifest: ManifestV2 = decode(ManifestKind::Ir, &bytes)?; // payload written as V1
// after
let manifest: ManifestV1 = decode(ManifestKind::Ir, &bytes)?; // decode with the writer's schema
Defensive patterns

Strategy: try-catch

Try / catch

// Rust
match baml_artifact::decode::<Manifest>(&bytes) {
    Ok(manifest) => use(manifest),
    Err(baml_artifact::Error::Decode { message, .. }) => {
        eprintln!("artifact payload unreadable: {message} — regenerate with matching toolchain");
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling the crate's decode path with a type `T: BorshDeserialize` whose in-memory layout expectation does not match the serialized payload — e.g., decoding with a different struct version than was encoded.

Common situations: A struct gained/lost fields between toolchain versions while the artifact format version wasn't bumped; decoding the payload with the wrong type parameter; artifacts produced by a mismatched generator reaching an updated runtime.

Understand the failure class

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/c7672cbeee92c7ea. Report an issue: GitHub.