apache/iceberg · error · java.lang.UnsupportedOperationException

Failed to read Variant %s of type %s as long

Error message

Failed to read Variant %s of type %s as long

What it means

Thrown by VariantRowDataWrapper.longValue: the Flink RowData getter requested a long, but the variant's actual primitive type is not a numeric family member representable as long (tinyint/smallint/int/bigint are handled; e.g. it holds a string, boolean, or double). The formatted message names the variant and its type — a read-schema/type mismatch on variant data.

Source

Thrown at flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/data/VariantRowDataWrapper.java:265

    return new GenericArrayData(elements);
  }

  private static int intValue(Variant variant) {
    return switch (variant.getType()) {
      case TINYINT -> variant.getByte();
      case SMALLINT -> variant.getShort();
      case INT -> variant.getInt();
      default -> throw new UnsupportedOperationException(errMsg(variant, "int"));
    };
  }

  private static long longValue(Variant variant) {
    return switch (variant.getType()) {
      case TINYINT -> variant.getByte();
      case SMALLINT -> variant.getShort();
      case INT -> variant.getInt();
      case BIGINT -> variant.getLong();
      default -> throw new UnsupportedOperationException(errMsg(variant, "long"));
    };
  }

  private static double doubleValue(Variant variant) {
    return switch (variant.getType()) {
      case FLOAT -> variant.getFloat();
      case DOUBLE -> variant.getDouble();
      default -> throw new UnsupportedOperationException(errMsg(variant, "double"));
    };
  }

  private static DecimalData decimalDataValue(Variant variant, DecimalType decimalType) {
    return DecimalData.fromBigDecimal(
        variant.getDecimal(), decimalType.getPrecision(), decimalType.getScale());
  }

  private static TimestampData timestampValue(Variant variant, int precision) {
    return switch (variant.getType()) {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Ensure the writer stores an integral variant for BIGINT columns
  2. Use getDouble when the variant is floating point, or fix the RowType to DOUBLE
  3. Cast the value upstream to a long before writing it as a variant

Example fix

// before
row.getLong(2); // variant is DOUBLE -> throws
// after
row.getDouble(2); // or rewrite variants as long
Defensive patterns

Strategy: try-catch

Validate before calling

switch (variant.getType()) {
  case TINYINT: case SMALLINT: case INT: case BIGINT: break;
  default: /* not a long; use appropriate accessor */ }
}

Type guard

boolean isIntegral(Variant v) {
  switch (v.getType()) {
    case TINYINT: case SMALLINT: case INT: case BIGINT: return true;
    default: return false;
  }
}

Try / catch

try { return row.getLong(pos); }
catch (UnsupportedOperationException e) { /* variant is non-integral; route to double/decimal accessor */ }

Prevention

When it happens

Trigger: Calling getLong on a VariantRowDataWrapper column whose variant is not an integral type, or elementValue resolving a BIGINT field whose variant is e.g. a double.

Common situations: Column type evolution (bigint -> double) or writers emitting non-integral variants into long-typed fields.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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