{"record":{"id":"5f15dbb49577f32f","repo":"dbt-labs/dbt-core","slug":"relationconfig-should-serialize","errorCode":null,"errorMessage":"RelationConfig should serialize","messagePattern":"RelationConfig should serialize","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-adapter/src/time_machine/serializable_impls.rs","lineNumber":463,"sourceCode":"                RelationType::MaterializedView,\n                serde_json::json!({\n                    \"partitioned_by\": {\"partition_by\": [\"event_date\"]}\n                }),\n            ),\n            (\n                RelationType::StreamingTable,\n                serde_json::json!({\n                    \"comment\": {\"comment\": \"streaming events\", \"persist\": true},\n                    \"partitioned_by\": {\"partition_by\": [\"event_date\"]}\n                }),\n            ),\n        ];\n\n        for (relation_type, payload) in cases {\n            let ctx = databricks_ctx(relation_type);\n            let original = RelationConfig::from_time_machine_json(&payload, &ctx)\n                .expect(\"RelationConfig should deserialize\");\n            let recorded = serialize_object(&original).expect(\"RelationConfig should serialize\");\n            let restored = json_to_value_with_context(&recorded, &ctx);\n            assert_eq!(\n                serialize_object(&restored),\n                Some(recorded),\n                \"RelationConfig should roundtrip for {relation_type:?}\"\n            );\n        }\n    }\n\n    /// Reproduces the Databricks same-version replay break.\n    ///\n    /// `tbl_properties::to_jinja` emits TWO keys for the `tblproperties` component:\n    /// the `tblproperties` sub-map (with `pipelines.pipelineId` filtered out) AND a\n    /// separate top-level `pipeline_id`. But `component_from_recorded` only reads back\n    /// `val.get(\"tblproperties\")` — the `pipeline_id` is silently dropped on deserialize.\n    ///\n    /// For any DLT-backed relation (streaming tables, materialized views), the recorded\n    /// `pipeline_id` is a non-null string. On replay the recorded result is deserialized","sourceCodeStart":445,"sourceCodeEnd":481,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-adapter/src/time_machine/serializable_impls.rs#L445-L481","documentation":"Test panic from `serialize_object(&original).expect(\"RelationConfig should serialize\")` in serializable_impls.rs:463. `serialize_object` goes through the time-machine registry (TYPE_ID-based); it returns None/errors when the value's concrete type is not registered for serialization or a component cannot be rendered back to JSON. This panic means a freshly deserialized RelationConfig cannot be written back to recording JSON for its Databricks relation type.","triggerScenarios":"`serialize_object` called on a RelationConfig whose TYPE_ID (`RelationConfig`) is missing from the registry, or whose per-relation-type components (tags, column_tags, tblproperties, partitioned_by, comment) cannot be converted to recorded JSON for the ctx's RelationType.","commonSituations":"Forgetting to register RelationConfig (or a new component) in the time-machine serialization registry after refactoring; a component only implemented for some RelationTypes (e.g. tblproperties on Table but not View); ctx.with_relation_type set to a type the serializer has no branch for.","solutions":["Confirm RelationConfig::TYPE_ID is registered in the time-machine serialization registry (see test_type_ids_are_stable).","Check serialize_object's per-relation-type branches cover all RelationTypes used in the test (Table, View, MaterializedView, StreamingTable).","Add the missing component serialization (to_jinja/to recorded JSON path) for the failing relation type.","Return the registry lookup error instead of Option so failures are diagnosable, then rerun the test."],"exampleFix":"// before\nlet recorded = serialize_object(&original).expect(\"RelationConfig should serialize\");\n// after\nlet recorded = serialize_object(&original)\n    .unwrap_or_else(|| panic!(\"RelationConfig failed to serialize for {relation_type:?}\"));","handlingStrategy":"try-catch","validationCode":"if RelationConfig::TYPE_ID_registry_missing() {\n    panic!(\"RelationConfig not registered for time-machine serialization\");\n}","typeGuard":"fn serializable(v: &minijinja::Value) -> bool {\n    serialize_object(v).is_some()\n}","tryCatchPattern":"let recorded = serialize_object(&original).unwrap_or_else(|| {\n    log::error(\"RelationConfig unserializable for this relation type\");\n    fallback_to_raw_payload()\n});","preventionTips":["Keep test_type_ids_are_stable-style registry tests green in CI.","Add serialize branches when introducing new relation types.","Prefer Result-returning serialize helpers over Option to surface root causes."],"tags":["rust","databricks","serialization","relation-config"],"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"}