apache/iceberg · error

Cannot parse type string: variant is not a primitive type

Error message

Cannot parse type string: variant is not a primitive type

What it means

Thrown by Types.fromPrimitiveString when fromTypeName successfully parsed the string but the result is a nested (non-primitive) type. fromPrimitiveString only accepts primitive types; note the hardcoded message mentions 'variant' because VariantType is the notable nested type reachable via a plain name lookup.

Source

Thrown at api/src/main/java/org/apache/iceberg/types/Types.java:115

    if (fixed.matches()) {
      return FixedType.ofLength(Integer.parseInt(fixed.group(1)));
    }

    Matcher decimal = DECIMAL.matcher(lowerTypeString);
    if (decimal.matches()) {
      return DecimalType.of(Integer.parseInt(decimal.group(1)), Integer.parseInt(decimal.group(2)));
    }

    throw new IllegalArgumentException("Cannot parse type string to primitive: " + typeString);
  }

  public static PrimitiveType fromPrimitiveString(String typeString) {
    Type type = fromTypeName(typeString);
    if (type.isPrimitiveType()) {
      return type.asPrimitiveType();
    }

    throw new IllegalArgumentException("Cannot parse type string: variant is not a primitive type");
  }

  public static class BooleanType extends PrimitiveType {
    private static final BooleanType INSTANCE = new BooleanType();

    public static BooleanType get() {
      return INSTANCE;
    }

    @Override
    public TypeID typeId() {
      return TypeID.BOOLEAN;
    }

    @Override
    public String toString() {
      return "boolean";
    }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Use Types.fromTypeName instead if nested types are acceptable
  2. Verify the column's type is primitive before requesting a PrimitiveType (check typeID, e.g. VariantType.typeId() == Variant)
  3. Handle variant columns separately from primitive columns in your logic

Example fix

// before
PrimitiveType p = Types.fromPrimitiveString("variant");
// after
Type t = Types.fromTypeName("variant");
if (t.isPrimitiveType()) {
  PrimitiveType p = t.asPrimitiveType();
}
Defensive patterns

Strategy: type-guard

Validate before calling

Type t = Types.fromTypeName(typeString);
if (!t.isPrimitiveType()) { throw new IllegalArgumentException("Expected primitive type, got: " + t); }

Type guard

PrimitiveType asPrimitiveOrNull(String typeString) {
  Type t = Types.fromTypeName(typeString);
  return t.isPrimitiveType() ? t.asPrimitiveType() : null;
}

Try / catch

try {
  PrimitiveType p = Types.fromPrimitiveString(typeString);
} catch (IllegalArgumentException e) {
  // handle nested type: fall back to Types.fromTypeName and branch on nested types
}

Prevention

When it happens

Trigger: Calling Types.fromPrimitiveString("variant") (or any type name that maps to a nested type such as a list/map/struct identifier) — the string parses fine but is not a PrimitiveType.

Common situations: Code that assumes a column is primitive (e.g. building predicates or ID-to-type maps) encountering a variant or other nested column type defined in the schema.

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/6dcdaf3bb2ec5357. Report an issue: GitHub.