apache/iceberg · error · UnsupportedOperationException

Unsupported type: " + primitive

Error message

Unsupported type: " + primitive

What it means

After the logical-type dispatch, the dictionary accessor path also switches on the raw PrimitiveTypeName (physical type); any physical type not handled (e.g. BOOLEAN, FLOAT, INT96-unmapped, or exotic types) hits the default branch and throws 'Unsupported type: ' + primitive. The vectorized dictionary reader supports only a fixed set of physical types.

Source

Thrown at arrow/src/main/java/org/apache/iceberg/arrow/vectorized/GenericArrowVectorAccessorFactory.java:178

    } else {
      switch (primitive.getPrimitiveTypeName()) {
        case FIXED_LEN_BYTE_ARRAY:
        case BINARY:
          return new DictionaryBinaryAccessor<>(
              (IntVector) vector, dictionary, stringFactorySupplier.get());
        case FLOAT:
          return new DictionaryFloatAccessor<>((IntVector) vector, dictionary);
        case INT64:
          return new DictionaryLongAccessor<>((IntVector) vector, dictionary);
        case INT96:
          // Impala & Spark used to write timestamps as INT96 by default. For backwards
          // compatibility we try to read INT96 as timestamps. But INT96 is not recommended
          // and deprecated (see https://issues.apache.org/jira/browse/PARQUET-323)
          return new DictionaryTimestampInt96Accessor<>((IntVector) vector, dictionary);
        case DOUBLE:
          return new DictionaryDoubleAccessor<>((IntVector) vector, dictionary);
        default:
          throw new UnsupportedOperationException("Unsupported type: " + primitive);
      }
    }
  }

  @SuppressWarnings("checkstyle:CyclomaticComplexity")
  private ArrowVectorAccessor<DecimalT, Utf8StringT, ArrayT, ChildVectorT> getPlainVectorAccessor(
      FieldVector vector, PrimitiveType primitive) {
    if (vector instanceof BitVector) {
      return new BooleanAccessor<>((BitVector) vector);
    } else if (vector instanceof IntVector) {
      if (isDecimal(primitive)) {
        return new IntBackedDecimalAccessor<>((IntVector) vector, decimalFactorySupplier.get());
      }
      return new IntAccessor<>((IntVector) vector);
    } else if (vector instanceof BigIntVector) {
      if (isDecimal(primitive)) {
        return new LongBackedDecimalAccessor<>((BigIntVector) vector, decimalFactorySupplier.get());
      }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Check the column's physical type and exclude it from vectorized reads (use the row reader)
  2. Rewrite data with supported physical types (INT32/INT64/BINARY/FIXED_LEN_BYTE_ARRAY/DOUBLE/FLBA timestamps)
  3. Upgrade Iceberg if a newer version added an accessor for the type
Defensive patterns

Strategy: fallback

Validate before calling

if (!SUPPORTED_PHYSICAL_TYPES.contains(primitive.getPrimitiveTypeName())) { useRowReader(column); }

Try / catch

try { accessor = factory.getVectorAccessor(holder); } catch (UnsupportedOperationException e) { if (e.getMessage().startsWith("Unsupported type:")) { accessor = rowAccessor(holder); } else throw e; }

Prevention

When it happens

Trigger: Requesting a vectorized accessor for a dictionary-encoded column whose physical Parquet type (e.g. FLOAT, BOOLEAN, INTERVAL) has no Dictionary*Accessor implementation.

Common situations: Third-party Parquet files with physical types Iceberg's vectorized reader never supported; expecting full type coverage in vectorized reads when it is limited to a known subset.

Related errors


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