apache/flink · error · RuntimeException

Unknown field name '%s' for mapping to a row position. Avail

Error message

Unknown field name '%s' for mapping to a row position. Available names are: %s

What it means

RowSerializer.getPositionByName() looks up a field name in the positionByName map to find its serializer position. If the field name is not present in the map, this RuntimeException is thrown with a String.format message listing the unknown name and all available names. The serializer's schema and the Row's field names must agree exactly — any field name in the Row that is not in the serializer's name→position map triggers this.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/RowSerializer.java:432

        RowSerializer that = (RowSerializer) o;
        return supportsRowKind == that.supportsRowKind
                && Arrays.equals(fieldSerializers, that.fieldSerializers);
    }

    @Override
    public int hashCode() {
        int result = Objects.hash(supportsRowKind);
        result = 31 * result + Arrays.hashCode(fieldSerializers);
        return result;
    }

    // --------------------------------------------------------------------------------------------

    private int getPositionByName(String fieldName) {
        assert positionByName != null;
        final Integer targetPos = positionByName.get(fieldName);
        if (targetPos == null) {
            throw new RuntimeException(
                    String.format(
                            "Unknown field name '%s' for mapping to a row position. "
                                    + "Available names are: %s",
                            fieldName, positionByName.keySet()));
        }
        return targetPos;
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        this.mask = new boolean[rowKindOffset + fieldSerializers.length];
        this.reuseRowPositionBased = new Row(fieldSerializers.length);
    }

    // --------------------------------------------------------------------------------------------
    // Serialization utilities
    // --------------------------------------------------------------------------------------------

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Ensure the field names in the Row exactly match the keys of the serializer's positionByName map (including case).
  2. Update the RowTypeInfo / RowSerializer field-name map whenever a column is renamed or added.
  3. If the Row may carry extra fields not in the serializer schema, project it to only the known fields before serialization.
  4. Use a shared schema definition (e.g., a Schema or TableSchema) to build both the Row and the serializer consistently.

Example fix

// before — Row field name 'userName' not in serializer schema
LinkedHashMap<String, Integer> names = new LinkedHashMap<>();
names.put("id", 0); names.put("name", 1);
RowSerializer ser = new RowSerializer(new TypeSerializer[]{intSer, strSer}, names);
Row row = Row.withNames().setField("id", 1).setField("userName", "a");
ser.serialize(row, output); // 'userName' not in {id, name} → exception

// after — Row field names match serializer schema
Row row = Row.withNames().setField("id", 1).setField("name", "a");
ser.serialize(row, output); // OK
Defensive patterns

Strategy: validation

Validate before calling

// Validate that all field names in the Row are known to the serializer schema
public static void validateFieldNames(Row row, Set<String> schemaNames) {
    Set<String> rowNames = row.getFieldNames(false);
    if (rowNames == null) return; // position-based, skip
    for (String name : rowNames) {
        if (!schemaNames.contains(name)) {
            throw new IllegalArgumentException(
                "Unknown field name '" + name + "'; known names: " + schemaNames);
        }
    }
}

Type guard

public static boolean allNamesInSchema(Row row, Set<String> schemaNames) {
    Set<String> rowNames = row.getFieldNames(false);
    if (rowNames == null) return true;
    return schemaNames.containsAll(rowNames);
}

Try / catch

try {
    serializer.serialize(namedRecord, output);
} catch (RuntimeException e) {
    if (e.getMessage().contains("Unknown field name")) {
        log.error("Row has field names not in serializer schema: {}",
            e.getMessage());
        // fix the Row or update the serializer schema
    }
    throw e;
}

Prevention

When it happens

Trigger: During name-based copy, serialize, or deserialize, the code calls getPositionByName(fieldName) for each field in a name-based Row. If the Row contains a field name that was not provided when the serializer's positionByName map was constructed, the lookup returns null and this exception fires.

Common situations: The Row was created with field names that differ from the serializer's schema (typo, renamed column, different casing); a schema evolution added a new named field to the Row but the serializer was not updated with the new name; two sources with overlapping-but-different field names are unioned; the field-name set in the RowTypeInfo does not match the names used by the upstream operator that created the Row.

Related errors


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