{"record":{"id":"6ae11162812eb32e","repo":"apache/iceberg","slug":"unsupported-type-decimal","errorCode":null,"errorMessage":"Unsupported type: decimal","messagePattern":"Unsupported type: decimal","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"arrow/src/main/java/org/apache/iceberg/arrow/vectorized/ArrowVectorAccessor.java","lineNumber":77,"sourceCode":"\n  public long getLong(int rowId) {\n    throw new UnsupportedOperationException(\"Unsupported type: long\");\n  }\n\n  public float getFloat(int rowId) {\n    throw new UnsupportedOperationException(\"Unsupported type: float\");\n  }\n\n  public double getDouble(int rowId) {\n    throw new UnsupportedOperationException(\"Unsupported type: double\");\n  }\n\n  public byte[] getBinary(int rowId) {\n    throw new UnsupportedOperationException(\"Unsupported type: binary\");\n  }\n\n  public DecimalT getDecimal(int rowId, int precision, int scale) {\n    throw new UnsupportedOperationException(\"Unsupported type: decimal\");\n  }\n\n  public Utf8StringT getUTF8String(int rowId) {\n    throw new UnsupportedOperationException(\"Unsupported type: UTF8String\");\n  }\n\n  public ArrayT getArray(int rowId) {\n    throw new UnsupportedOperationException(\"Unsupported type: array\");\n  }\n\n  public ChildVectorT childColumn(int pos) {\n    if (childColumns != null) {\n      return childColumns[pos];\n    } else {\n      throw new IndexOutOfBoundsException(\"Child columns is null hence cannot find index: \" + pos);\n    }\n  }\n","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/arrow/src/main/java/org/apache/iceberg/arrow/vectorized/ArrowVectorAccessor.java#L59-L95","documentation":"ArrowVectorAccessor is an abstract base whose default getDecimal implementation throws this UnsupportedOperationException. It exists so concrete accessors only implement the read methods their underlying Arrow vector actually supports; calling getDecimal on an accessor whose column is not a decimal-typed vector reaches the base-class stub and throws. The message reflects that this accessor type has no decimal decoding path.","triggerScenarios":"Calling GenericArrowVectorAccessorFactory.getVectorAccessor(...).getDecimal(rowId, precision, scale) on an accessor for a non-decimal column (e.g. a binary or int vector accessor), or using a subclass that did not override getDecimal. The RAISED IN info shows it is reached via toDecimalVector, i.e. during vector-to-row materialization of a column that is not actually decimal.","commonSituations":"Vectorized-read pipelines (e.g. Spark's vectorized Iceberg reader) converting batch columns to row objects where the column's Iceberg type and the accessor's vector type diverge; using a batch/vectorization config that routes decimal columns to a plain binary accessor; upgrading Iceberg where a previously overridden method is now the base stub.","solutions":["Verify the Iceberg column type is decimal before calling getDecimal on the vector accessor","Check which concrete ArrowVectorAccessor subclass you hold; only Decimal accessors implement getDecimal","Ensure vectorized reads are configured consistently so decimal columns get DecimalLong/DecimalInt accessors","If the column type is dynamic, branch on the accessor/vector type instead of assuming decimal"],"exampleFix":"// before\nbyte[] d = accessor.getDecimal(rowId, precision, scale); // throws for non-decimal columns\n// after\nif (accessor instanceof ArrowColumnAccessor /* or type is decimal */) {\n  byte[] d = accessor.getDecimal(rowId, precision, scale);\n} else {\n  Object v = accessor.getSingleValue(rowId); // generic path\n}","handlingStrategy":"type-guard","validationCode":"if (!columnType.typeId().equals(TypeID.DECIMAL)) { throw new IllegalArgumentException(columnType + \" is not decimal\"); }","typeGuard":"boolean isDecimalAccessor(ArrowVectorAccessor<?,?,?,?> a) { return a instanceof DecimalArrowAccessor || a instanceof DictionaryDecimalLongAccessor || a instanceof DictionaryDecimalIntAccessor; }","tryCatchPattern":"try { return accessor.getDecimal(rowId, precision, scale); } catch (UnsupportedOperationException e) { if (e.getMessage().contains(\"decimal\")) { return genericRow(rowId); } throw e; }","preventionTips":["Match typed getters to the column's Iceberg type before materializing rows","Route non-decimal columns through getSingleValue or the generic accessor path","Keep vectorized-read config consistent with schema expectations in tests"],"tags":["arrow","vectorized-read","unsupported-type"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}