dbt-labs/dbt-core · error · InvalidArgument

Not all tables have the same column types!

Error message

Not all tables have the same column types!

What it means

Thrown when constructing a `TableSet` (`try_new`) from multiple tables whose column types differ. By default (unless fork/merge behavior is enabled via `is_fork`), a TableSet requires all member tables to share identical column types, validated against the sample table. This keeps grouping/merging across the set well-defined.

Source

Thrown at crates/dbt-agate/src/table_set.rs:142

        keys: Vec<Value>,
        key_name: Option<String>,
        key_type: Option<crate::DataType>,
        is_fork: bool,
    ) -> Result<Arc<Self>, Error> {
        let key_name = key_name.unwrap_or_else(|| "group".to_string());
        let key_type = key_type.unwrap_or_else(|| crate::DataType::new("Text".to_string()));
        let sample_table = tables.first().map(Arc::clone);

        let column_types = sample_table.as_ref().map(|t| t.column_types_as_tuple());
        let column_names = sample_table.as_ref().map(|t| t.column_names_as_tuple());

        if !is_fork {
            for table in &tables {
                let self_column_types = column_types
                    .as_ref()
                    .expect("column types from sample table");
                if table.column_types_as_tuple() != *self_column_types {
                    return Err(Error::new(
                        ErrorKind::InvalidArgument,
                        "Not all tables have the same column types!",
                    ));
                }

                let self_column_names = column_names
                    .as_ref()
                    .expect("column names from sample table");
                if table.column_names_as_tuple() != *self_column_names {
                    return Err(Error::new(
                        ErrorKind::InvalidArgument,
                        "Not all tables have the same column names!",
                    ));
                }
            }
        }

        let repr = TableSetRepr {

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Align schemas so all tables share the same column types (cast columns explicitly, e.g. cast all to Text)
  2. Use `column_types` arguments when creating the source tables to force consistent types
  3. If intentional divergence is desired, use the fork behavior (`is_fork` path) that skips validation
  4. Normalize the data before building the TableSet (fill nulls, standardize formats)

Example fix

// before
TableSet(tables)  # column 'amount' is Number in one table, Text in another
// after
tables = [t.cast_column('amount', agate.Number()) for t in raw_tables]
TableSet(tables)
Defensive patterns

Strategy: validation

Validate before calling

types = [t.column_types_as_tuple() for t in tables]
if any(ty != types[0] for ty in types[1:]):
    raise ValueError('tables must share identical column types')

Type guard

null

Try / catch

try:
    ts = agate.TableSet(tables, key_name='group')
except Exception as e:
    if 'same column types' in str(e):
        tables = [align_column_types(t, types[0]) for t in tables]
        ts = agate.TableSet(tables, key_name='group')
    else:
        raise

Prevention

When it happens

Trigger: Calling `TableSet::try_new` (Python `agate.TableSet`) with tables where at least one table's column types tuple differs from the others — e.g. a column inferred as Number in one table and Text in another.

Common situations: Combining CSVs where one file has an empty cell forcing a Text column; tables built from different queries with drifted schemas; a version change altering type inference for one input.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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