dbt-labs/dbt-core · error · InvalidArgument

Not all tables have the same column names!

Error message

Not all tables have the same column names!

What it means

Thrown when constructing a `TableSet` (`try_new`) from multiple tables whose column names differ. All tables in a TableSet must have identical column names (validated against the sample table) unless the fork path is taken; a name mismatch makes set-wide operations ambiguous, so this InvalidArgument error is raised.

Source

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

        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 {
            key_name,
            key_type,
            sample_table,
            column_types,
            column_names,
            tables,
            keys,
        };
        Ok(Arc::new(repr))
    }

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Rename columns so all tables match (`rename` / `rename_column` on the divergent tables)
  2. Reorder/select columns to a common set before constructing the TableSet
  3. Use the fork behavior (`is_fork` path) if differing schemas are intentional
  4. Standardize the upstream queries/files so column names stay stable

Example fix

// before
TableSet(tables)  # one table has 'region', others have 'area'
// after
tables = [t.rename_column('area', 'region') if 'area' in t.column_names else t for t in raw_tables]
TableSet(tables)
Defensive patterns

Strategy: validation

Validate before calling

names = [t.column_names_as_tuple() for t in tables]
if any(n != names[0] for n in names[1:]):
    raise ValueError('tables must share identical column names')

Type guard

null

Try / catch

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

Prevention

When it happens

Trigger: Calling `TableSet::try_new` with tables where at least one table's column names tuple differs from the others — reordered, renamed, missing, or extra columns.

Common situations: Combining CSVs from different periods where a column was renamed; tables from queries with SELECT column order changed; schema drift between sources.

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/65e9e884cf5d28c7. Report an issue: GitHub.