apache/flink · error · IllegalArgumentException

Accessing a field by position is not supported in name-based

Error message

Accessing a field by position is not supported in name-based field mode.

What it means

Row supports two access modes: position-based (fields stored in an array, fieldByPosition != null) and name-based (fields in a map). getField(int pos) only works in position-based mode; if the row was created with Row.withNames() / Row.ofKind-with-names (so only fieldByName/positionByName exist and fieldByPosition is null), positional access is rejected with this IllegalArgumentException.

Source

Thrown at flink-core/src/main/java/org/apache/flink/types/Row.java:257

        } else {
            assert fieldByName != null;
            return fieldByName.size();
        }
    }

    /**
     * Returns the field's content at the specified field position.
     *
     * <p>Note: The row must operate in position-based field mode.
     *
     * @param pos the position of the field, 0-based
     * @return the field's content at the specified position
     */
    public @Nullable Object getField(int pos) {
        if (fieldByPosition != null) {
            return fieldByPosition[pos];
        } else {
            throw new IllegalArgumentException(
                    "Accessing a field by position is not supported in name-based field mode.");
        }
    }

    /**
     * Returns the field's content at the specified field position.
     *
     * <p>Note: The row must operate in position-based field mode.
     *
     * <p>This method avoids a lot of manual casting in the user implementation.
     *
     * @param pos the position of the field, 0-based
     * @return the field's content at the specified position
     */
    @SuppressWarnings("unchecked")
    public <T> T getFieldAs(int pos) {
        return (T) getField(pos);
    }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Use getField(String name) / getFieldAs(name, type) on name-based rows
  2. Create the row position-based with Row.of(...) / Row.ofKind(...) if positional access is required
  3. Branch on the mode with row.getFieldNames(true) != null before access, or normalize rows to one mode at the boundary

Example fix

// before
Row row = Row.withNames();
row.setField("id", 42);
Object v = row.getField(0); // throws

// after
Object v = row.getField("id");
Defensive patterns

Strategy: type-guard

Validate before calling

boolean positionBased = row.getFieldNames(true) == null || /* hybrid rows also have fieldByPosition */ row.getField(0) != null;

Type guard

static boolean isPositionBased(Row row) {
    return row.getFieldNames(true) == null;
}
// usage: if (isPositionBased(row)) v = row.getField(pos); else v = row.getField(name);

Try / catch

catch (IllegalArgumentException e) { throw new IllegalStateException("Row mode mismatch; expected position-based", e); }

Prevention

When it happens

Trigger: Calling row.getField(pos) on a Row created via Row.withNames(), Row.withNames(RowKind, ...), or one whose fields were set via setField(String, Object); also hybrid rows where only names were provided.

Common situations: Connector or function code written for position-based rows receiving name-based rows produced by the Table/SQL layer or a source that sets field names; mixing Row.of(...) and Row.withNames() creation paths in one pipeline.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/01b2a34d6d7a934e. Report an issue: GitHub.