apache/seatunnel · error · IllegalArgumentException

Schema config can't contains both [fields] and [columns], pl

Error message

Schema config can't contains both [fields] and [columns], please correct your config first

What it means

ReadonlyConfigParser.parse rejects schema configurations that define columns via both the legacy/new 'fields' key and the 'columns' key. The two schema declaration styles are mutually exclusive because they would produce an ambiguous TableSchema. The parser forces users to pick one style.

Source

Thrown at seatunnel-api/src/main/java/org/apache/seatunnel/api/table/catalog/schema/ReadonlyConfigParser.java:59

    private final TableSchemaParser.ColumnParser<ReadonlyConfig> columnParser = new ColumnParser();
    private final TableSchemaParser.FieldParser<ReadonlyConfig> fieldParser = new FieldParser();
    private final TableSchemaParser.ConstraintKeyParser<ReadonlyConfig> constraintKeyParser =
            new ConstraintKeyParser();
    private final TableSchemaParser.PrimaryKeyParser<ReadonlyConfig> primaryKeyParser =
            new PrimaryKeyParser();

    @Override
    public TableSchema parse(ReadonlyConfig readonlyConfig) {
        ReadonlyConfig schemaConfig =
                readonlyConfig
                        .getOptional(ConnectorCommonOptions.SCHEMA)
                        .map(ReadonlyConfig::fromMap)
                        .orElseThrow(
                                () -> new IllegalArgumentException("Schema config can't be null"));

        if (readonlyConfig.getOptional(ConnectorCommonOptions.FIELDS).isPresent()
                && schemaConfig.getOptional(ConnectorCommonOptions.COLUMNS).isPresent()) {
            throw new IllegalArgumentException(
                    "Schema config can't contains both [fields] and [columns], please correct your config first");
        }
        TableSchema.Builder tableSchemaBuilder = TableSchema.builder();
        if (readonlyConfig.getOptional(ConnectorCommonOptions.FIELDS).isPresent()) {
            // we use readonlyConfig here to avoid flatten, this is used to solve the t.x.x as field
            // key
            tableSchemaBuilder.columns(fieldParser.parse(readonlyConfig));
        }

        if (schemaConfig.getOptional(ConnectorCommonOptions.COLUMNS).isPresent()) {
            tableSchemaBuilder.columns(columnParser.parse(schemaConfig));
        }
        if (schemaConfig.getOptional(ConnectorCommonOptions.PRIMARY_KEY).isPresent()) {
            tableSchemaBuilder.primaryKey(primaryKeyParser.parse(schemaConfig));
        }
        if (schemaConfig.getOptional(ConnectorCommonOptions.CONSTRAINT_KEYS).isPresent()) {
            tableSchemaBuilder.constraintKey(constraintKeyParser.parse(schemaConfig));
        }

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Remove either the fields block or the columns block from the schema config, keeping one style
  2. If migrating, translate fields entries to the columns format (or vice versa) and delete the old key
  3. Search config files/merge scripts for both keys coexisting in the same schema block

Example fix

// before
schema {
  fields { id = bigint }
  columns [{ name = id, type = bigint }]
}
// after
schema {
  columns [{ name = id, type = bigint }]
}
Defensive patterns

Strategy: validation

Validate before calling

Map<String,Object> schema = (Map<String,Object>) config.get("schema");
if (schema != null && schema.containsKey("fields") && schema.containsKey("columns"))
    throw new IllegalArgumentException("Use either schema.fields or schema.columns, not both");

Try / catch

try { schema = new ReadonlyConfigParser<>(TableSchema.class).parse(readonlyConfig); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("Fix schema config: " + e.getMessage()); }

Prevention

When it happens

Trigger: A source/sink config block contains schema { fields = {...} } and also schema { columns = [...] } (or nested options with both ConnectorCommonOptions.FIELDS and COLUMNS present).

Common situations: Merging example configs when migrating between config styles, combining a vendor-provided template with hand-edits, or programmatic config assembly that appends both keys.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/6b5aacb7b1884295. Report an issue: GitHub.