{"record":{"id":"8426735a97507a5b","repo":"dbt-labs/dbt-core","slug":"existing-columns-must-contain-column-objects","errorCode":null,"errorMessage":"existing_columns must contain Column objects","messagePattern":"existing_columns must contain Column objects","errorType":"exception","errorClass":"minijinja::Error::InvalidOperation","httpStatus":null,"severity":"error","filePath":"crates/dbt-adapter/src/adapter/adapter_impl.rs","lineNumber":4659,"sourceCode":"\n        if self.adapter_type() != Databricks && self.adapter_type() != Spark {\n            return Err(minijinja::Error::new(\n                minijinja::ErrorKind::InvalidOperation,\n                \"parse_columns_and_constraints is only available for Databricks/Spark adapter\",\n            ));\n        }\n\n        let columns: Vec<Column> = existing_columns\n            .try_iter()\n            .map_err(|e| {\n                minijinja::Error::new(\n                    minijinja::ErrorKind::InvalidOperation,\n                    format!(\"existing_columns must be iterable: {e}\"),\n                )\n            })?\n            .map(|v| {\n                v.downcast_object_ref::<Column>().cloned().ok_or_else(|| {\n                    minijinja::Error::new(\n                        minijinja::ErrorKind::InvalidOperation,\n                        \"existing_columns must contain Column objects\",\n                    )\n                })\n            })\n            .collect::<Result<Vec<_>, _>>()?;\n\n        let model_columns_map: BTreeMap<String, DbtColumn> =\n            minijinja_value_to_typed_struct(model_columns.clone()).map_err(|e| {\n                minijinja::Error::new(\n                    minijinja::ErrorKind::SerdeDeserializeError,\n                    format!(\"model_columns: {e}\"),\n                )\n            })?;\n\n        let model_constraints_vec: Vec<ModelConstraint> =\n            minijinja_value_to_typed_struct(model_constraints.clone()).map_err(|e| {\n                minijinja::Error::new(","sourceCodeStart":4641,"sourceCodeEnd":4677,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-adapter/src/adapter/adapter_impl.rs#L4641-L4677","documentation":"After successful iteration, every element of existing_columns must be a Column object; the code downcasts each Value to Column and raises InvalidOperation 'existing_columns must contain Column objects' on the first element that is not one. The adapter needs typed Column objects to extract names/types and build constraints.","triggerScenarios":"existing_columns is iterable but contains plain dicts, strings, or other Jinja values instead of Column objects — e.g. a hand-built list of {name, type} dicts.","commonSituations":"Constructing columns manually in a macro as dicts instead of using api.Column / the adapter's Column type; deserializing columns from JSON into plain maps; mixing Column objects with raw values in one list.","solutions":["Build elements with the Column type (e.g. api.Column / adapter column class) instead of plain dicts.","Convert each dict into a Column before calling: Column(name=..., dtype=...).","Use get_columns_in_relation output directly, which already contains Column objects.","Filter out any non-Column entries (e.g. stray strings) from the list before the call."],"exampleFix":"// before\ncols = [{\"name\": \"id\", \"dtype\": \"int\"}]\nadapter.parse_columns_and_constraints(cols, model_columns, name)\n\n// after\ncols = [api.Column(\"id\", \"int\")]\nadapter.parse_columns_and_constraints(cols, model_columns, name)","handlingStrategy":"validation","validationCode":"def all_columns_are_objects(v):\n    return all(getattr(i, 'name', None) is not None or (isinstance(i, dict) and 'name' in i) for i in v)","typeGuard":"def is_column_obj(x):\n    return hasattr(x, 'name') and hasattr(x, 'dtype')","tryCatchPattern":"try:\n    parsed = adapter.parse_columns_and_constraints(existing, model_columns, name)\nexcept Exception as e:\n    if 'must contain Column objects' in str(e):\n        raise ValueError('Convert dicts to api.Column objects before calling parse_columns_and_constraints') from e\n    raise","preventionTips":["Construct column entries with the Column type, never raw dicts","Prefer reusing get_columns_in_relation output over hand-built lists","Convert JSON/dict column data into Column objects at the macro boundary","Keep mixed lists (objects + dicts) out of this API"],"tags":["adapter","databricks","type-mismatch","column"],"backgroundTag":"type-mismatch","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}