apache/iceberg · error · UnsupportedOperationException

Avro format doesn't support non-string as key type of map…

Error message

Avro format doesn't support non-string as key type of map. The key type is: %s

What it means

extractValueTypeToAvroMap validates the key type of a Flink MAP/MULTISET before building the Avro map schema. Avro maps only allow string keys, so if the key type is not in the CHARACTER_STRING family the converter rejects it. Avro simply cannot represent non-string-keyed maps.

Solutions

  1. Change the map key type to VARCHAR/CHAR (string) in the table schema.
  2. Restructure the data as an ARRAY<ROW<key,value>> instead of a non-string-keyed map.
  3. Cast keys to STRING upstream in the Flink job before writing to the Iceberg table.
  4. If only a MULTISET is intended, note MULTISET is supported by this method only for string element types; convert non-string multisets to MAP<STRING,INT> or arrays.

Example fix

// before
DataTypes.MAP(DataTypes.INT(), DataTypes.STRING())
// after
DataTypes.MAP(DataTypes.STRING(), DataTypes.STRING())
Defensive patterns

Strategy: validation

Validate before calling

// Check map key types before conversion
for (Map.Entry<String, LogicalType> e : fieldTypes.entrySet()) {
  if (e.getValue() instanceof MapType) {
    LogicalType key = ((MapType) e.getValue()).getKeyType();
    Preconditions.checkArgument(key.is(LogicalTypeFamily.CHARACTER_STRING),
        "Map key must be string: %s", e.getKey());
  }
}

Type guard

boolean hasStringMapKeys(org.apache.flink.table.types.logical.LogicalType t) {
  return !(t instanceof MapType)
      || ((MapType) t).getKeyType().is(LogicalTypeFamily.CHARACTER_STRING);
}

Prevention

When it happens

Trigger: Converting a Flink table schema containing MAP<INT, T>, MAP<BIGINT, T>, MULTISET<INT> (or any non-VARCHAR/CHAR key) to Avro via AvroSchemaConverter during Iceberg Avro write/serialization.

Common situations: Tables created from SQL with INTEGER-keyed maps or multisets; schemas ingested from sources like Kafka/Protobuf that use integer keys; converting a whole row schema that happens to include such a map.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/df161a4bdceca568. Report an issue: GitHub.

Appendix: source

Thrown at flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/formats/avro/typeutils/AvroSchemaConverter.java:611

        throw new UnsupportedOperationException(
            "Unsupported to derive Schema for type: " + logicalType);
    }
  }

  public static LogicalType extractValueTypeToAvroMap(LogicalType type) {
    LogicalType keyType;
    LogicalType valueType;
    if (type instanceof MapType) {
      MapType mapType = (MapType) type;
      keyType = mapType.getKeyType();
      valueType = mapType.getValueType();
    } else {
      MultisetType multisetType = (MultisetType) type;
      keyType = multisetType.getElementType();
      valueType = new IntType();
    }
    if (!keyType.is(LogicalTypeFamily.CHARACTER_STRING)) {
      throw new UnsupportedOperationException(
          "Avro format doesn't support non-string as key type of map. "
              + "The key type is: "
              + keyType.asSummaryString());
    }
    return valueType;
  }

  /** Returns schema with nullable true. */
  private static Schema nullableSchema(Schema schema) {
    return schema.isNullable()
        ? schema
        : Schema.createUnion(SchemaBuilder.builder().nullType(), schema);
  }
}

View on GitHub (pinned to 86d9c8fc54)