prestodb/presto · error · IllegalArgumentException

Table %s does not have column %s

Error message

Table %s does not have column %s

What it means

TpchMetadata.getColumnMetadata scans the TPC-H table metadata for a column matching the requested name and throws IllegalArgumentException 'Table %s does not have column %s' when none matches. It indicates the caller supplied a column name/handle that does not exist in the given TPC-H table.

Source

Thrown at presto-tpch/src/main/java/com/facebook/presto/tpch/TpchMetadata.java:476

    @VisibleForTesting
    TpchColumnHandle toColumnHandle(TpchColumn<?> column)
    {
        return new TpchColumnHandle(columnNaming.getName(column), getPrestoType(column));
    }

    @Override
    public ColumnMetadata getColumnMetadata(ConnectorSession session, ConnectorTableHandle tableHandle, ColumnHandle columnHandle)
    {
        ConnectorTableMetadata tableMetadata = getTableMetadata(session, tableHandle);
        String columnName = ((TpchColumnHandle) columnHandle).getColumnName();

        for (ColumnMetadata column : tableMetadata.getColumns()) {
            if (column.getName().equals(columnName)) {
                return column;
            }
        }
        throw new IllegalArgumentException(String.format("Table %s does not have column %s", tableMetadata.getTable(), columnName));
    }

    @Override
    public List<SchemaTableName> listTables(ConnectorSession session, Optional<String> filterSchema)
    {
        ImmutableList.Builder<SchemaTableName> builder = ImmutableList.builder();
        for (String schemaName : getSchemaNames(session, filterSchema)) {
            for (TpchTable<?> tpchTable : TpchTable.getTables()) {
                builder.add(new SchemaTableName(schemaName, tpchTable.getTableName()));
            }
        }
        return builder.build();
    }

    private TupleDomain<ColumnHandle> toTupleDomain(Map<TpchColumnHandle, Set<NullableValue>> predicate)
    {
        return TupleDomain.withColumnDomains(predicate.entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, entry -> {

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Verify the exact column name against the TPC-H table (e.g. 'nationkey', not 'nationKey')
  2. List actual columns via listTableColumns before lookup
  3. Re-acquire ColumnHandle objects from the connector metadata instead of caching across restarts/upgrades
  4. Check that the table handle refers to the intended table

Example fix

// before
metadata.getColumnMetadata(session, ordersHandle, "totalprice2");
// after
metadata.getColumnMetadata(session, ordersHandle, "totalprice");
Defensive patterns

Strategy: validation

Validate before calling

Set<String> cols = metadata.listTableColumns(session, SchemaTablePrefix.of(schema, table)).get(SchemaTableName.of(schema, table))
    .stream().map(ColumnMetadata::getName).collect(Collectors.toSet());
if (!cols.contains(columnName)) throw new IllegalArgumentException("Column " + columnName + " not in " + table);

Try / catch

try {
    ColumnMetadata cm = metadata.getColumnMetadata(session, tableHandle, columnName);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("does not have column")) {
        // fall back to listing columns and matching case-insensitively
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling connector getColumnMetadata with a columnName absent from the table's metadata, e.g. a ColumnHandle from a different table, a misnamed column, or a stale handle after version change.

Common situations: Case mismatch in column name (TPC-H columns are lowercase like 'nationkey'); using a column from lineitem on an orders table handle; deserialized handles from an older Presto version.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/0e80809993f3470e. Report an issue: GitHub.