dbt-labs/dbt-core · error

original value should be serializable via the time-machine r

Error message

original value should be serializable via the time-machine registry

What it means

Panic from `serialize_object(original).expect("original value should be serializable via the time-machine registry")` in the shared helper `assert_reserialization_fixed_point` (serializable_impls.rs:858). The helper verifies that a minijinja Value (Column or RelationObject) recorded by the time machine survives serialize -> deserialize -> re-serialize unchanged. serialize_object looks types up by TYPE_ID in the registry and returns None when the value's concrete type is not registered, so the expect panics — meaning replay cannot even record this object.

Source

Thrown at crates/dbt-adapter/src/time_machine/serializable_impls.rs:858

    //     let j1 = serialize(original);
    //     let restored = deserialize(j1);
    //     let j2 = serialize(restored);
    //     assert_eq!(j1, j2);   // <-- the invariant replay depends on
    //
    // The existing `*_roundtrip` tests only check accessors after ONE
    // deserialize; they do NOT assert this fixed point.
    // =========================================================================

    /// Assert `serialize(deserialize(serialize(original))) == serialize(original)`.
    ///
    /// `original` must already be a serializable jinja Value (i.e. `serialize_object`
    /// returns `Some`). Returns the first serialization for optional further checks.
    fn assert_reserialization_fixed_point(
        original: &minijinja::Value,
        ctx: &ReplayCallContext,
    ) -> serde_json::Value {
        let j1 = serialize_object(original)
            .expect("original value should be serializable via the time-machine registry");
        let restored = json_to_value_with_context(&j1, ctx);
        let j2 = serialize_object(&restored).expect(
            "reconstructed value should re-serialize via the time-machine registry \
             (if this is None, deserialize produced a non-registry type such as a plain map)",
        );
        assert_eq!(
            j1, j2,
            "reserialization must be a fixed point; serialize/deserialize are asymmetric.\n\
             first:  {j1:#}\n\
             second: {j2:#}"
        );
        j1
    }

    #[test]
    fn test_column_reserialization_fixed_point_snowflake_varchar() {
        // A VARCHAR(255) column as returned by e.g. get_columns_in_relation.
        let original = crate::column::Column::new(

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Check the object's TYPE_ID (e.g. `Column`, `RelationObject`) is registered in the time-machine serialization registry.
  2. For the failing fixture (Snowflake numeric/varchar or BigQuery nested struct), add serialization support for the unrepresentable field type.
  3. Ensure json_to_value_with_context reconstructs the registry type, not a plain map — the helper's second message diagnoses that case.
  4. Replace expect in the helper with context-rich panics that print the type id and payload to speed triage.

Example fix

// before
let j1 = serialize_object(original)
    .expect("original value should be serializable via the time-machine registry");
// after
let j1 = serialize_object(original)
    .unwrap_or_else(|| panic!("type {:?} not registered for time-machine serialization", original.type_name()));
Defensive patterns

Strategy: type-guard

Validate before calling

if !is_registered_type(value) {
    return Err(format!("{} is not registered for time-machine serialization", value.type_name()));
}

Type guard

fn is_registered_type(v: &minijinja::Value) -> bool {
    serialize_object(v).is_some()
}

Try / catch

let j1 = serialize_object(original).unwrap_or_else(|| {
    panic!("{} not serializable via time-machine registry", original.type_name())
});

Prevention

When it happens

Trigger: `serialize_object` called on minijinja Values wrapping Column (Snowflake varchar/numeric, BigQuery repeated/nested struct) or RelationObject (table, dynamic table) whose TYPE_ID is not registered, or whose struct fields cannot be converted to recorded JSON.

Common situations: Adding a new Column/RelationObject variant or field without registering it in the time-machine serialization registry; BigQuery nested/repeated struct fields lacking a recording representation; a deserialize path that returns a plain map instead of a registry type (then the second expect with the 'non-registry type' message fires).

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/dfb39fdf1b9ba08a. Report an issue: GitHub.