{"record":{"id":"dfb39fdf1b9ba08a","repo":"dbt-labs/dbt-core","slug":"original-value-should-be-serializable-via-the-time","errorCode":null,"errorMessage":"original value should be serializable via the time-machine registry","messagePattern":"original value should be serializable via the time-machine registry","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-adapter/src/time_machine/serializable_impls.rs","lineNumber":858,"sourceCode":"    //     let j1 = serialize(original);\n    //     let restored = deserialize(j1);\n    //     let j2 = serialize(restored);\n    //     assert_eq!(j1, j2);   // <-- the invariant replay depends on\n    //\n    // The existing `*_roundtrip` tests only check accessors after ONE\n    // deserialize; they do NOT assert this fixed point.\n    // =========================================================================\n\n    /// Assert `serialize(deserialize(serialize(original))) == serialize(original)`.\n    ///\n    /// `original` must already be a serializable jinja Value (i.e. `serialize_object`\n    /// returns `Some`). Returns the first serialization for optional further checks.\n    fn assert_reserialization_fixed_point(\n        original: &minijinja::Value,\n        ctx: &ReplayCallContext,\n    ) -> serde_json::Value {\n        let j1 = serialize_object(original)\n            .expect(\"original value should be serializable via the time-machine registry\");\n        let restored = json_to_value_with_context(&j1, ctx);\n        let j2 = serialize_object(&restored).expect(\n            \"reconstructed value should re-serialize via the time-machine registry \\\n             (if this is None, deserialize produced a non-registry type such as a plain map)\",\n        );\n        assert_eq!(\n            j1, j2,\n            \"reserialization must be a fixed point; serialize/deserialize are asymmetric.\\n\\\n             first:  {j1:#}\\n\\\n             second: {j2:#}\"\n        );\n        j1\n    }\n\n    #[test]\n    fn test_column_reserialization_fixed_point_snowflake_varchar() {\n        // A VARCHAR(255) column as returned by e.g. get_columns_in_relation.\n        let original = crate::column::Column::new(","sourceCodeStart":840,"sourceCodeEnd":876,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-adapter/src/time_machine/serializable_impls.rs#L840-L876","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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).","solutions":["Check the object's TYPE_ID (e.g. `Column`, `RelationObject`) is registered in the time-machine serialization registry.","For the failing fixture (Snowflake numeric/varchar or BigQuery nested struct), add serialization support for the unrepresentable field type.","Ensure json_to_value_with_context reconstructs the registry type, not a plain map — the helper's second message diagnoses that case.","Replace expect in the helper with context-rich panics that print the type id and payload to speed triage."],"exampleFix":"// before\nlet j1 = serialize_object(original)\n    .expect(\"original value should be serializable via the time-machine registry\");\n// after\nlet j1 = serialize_object(original)\n    .unwrap_or_else(|| panic!(\"type {:?} not registered for time-machine serialization\", original.type_name()));","handlingStrategy":"type-guard","validationCode":"if !is_registered_type(value) {\n    return Err(format!(\"{} is not registered for time-machine serialization\", value.type_name()));\n}","typeGuard":"fn is_registered_type(v: &minijinja::Value) -> bool {\n    serialize_object(v).is_some()\n}","tryCatchPattern":"let j1 = serialize_object(original).unwrap_or_else(|| {\n    panic!(\"{} not serializable via time-machine registry\", original.type_name())\n});","preventionTips":["Register TYPE_IDs for every new Column/RelationObject variant at introduction time.","Add BigQuery struct/repeated-field fixtures to fixed-point tests.","Ensure deserialize reconstructs registry types, never plain maps."],"tags":["rust","serialization","minijinja","registry","fixed-point"],"backgroundTag":"json-marshal-failed","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}