{"record":{"id":"80ab8e2d01c29f7c","repo":"apache/iceberg","slug":"unsupported-stats-offset","errorCode":null,"errorMessage":"Unsupported stats offset: ","messagePattern":"Unsupported stats offset: ","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/FieldStatsStruct.java","lineNumber":195,"sourceCode":"  public Integer avgValueSizeInBytes() {\n    return avgValueSize;\n  }\n\n  @Override\n  public int size() {\n    return struct.fields().size();\n  }\n\n  private Object getOffset(int offset) {\n    return switch (offset) {\n      case StatsUtil.LOWER_BOUND_OFFSET -> lowerBound();\n      case StatsUtil.UPPER_BOUND_OFFSET -> upperBound();\n      case StatsUtil.TIGHT_BOUNDS_OFFSET -> tightBounds;\n      case StatsUtil.VALUE_COUNT_OFFSET -> valueCount;\n      case StatsUtil.NULL_VALUE_COUNT_OFFSET -> nullValueCount;\n      case StatsUtil.NAN_VALUE_COUNT_OFFSET -> nanValueCount;\n      case StatsUtil.AVG_VALUE_SIZE_OFFSET -> avgValueSize;\n      default -> throw new UnsupportedOperationException(\"Unsupported stats offset: \" + offset);\n    };\n  }\n\n  @Override\n  public <C> C get(int pos, Class<C> javaClass) {\n    return javaClass.cast(getOffset(posToOffset[pos]));\n  }\n\n  private void setOffset(int offset, Object value) {\n    switch (offset) {\n      case StatsUtil.LOWER_BOUND_OFFSET -> setLowerBound(value);\n      case StatsUtil.UPPER_BOUND_OFFSET -> setUpperBound(value);\n      case StatsUtil.TIGHT_BOUNDS_OFFSET -> this.tightBounds = (Boolean) value;\n      case StatsUtil.VALUE_COUNT_OFFSET -> this.valueCount = (Long) value;\n      case StatsUtil.NULL_VALUE_COUNT_OFFSET -> this.nullValueCount = (Long) value;\n      case StatsUtil.NAN_VALUE_COUNT_OFFSET -> this.nanValueCount = (Long) value;\n      case StatsUtil.AVG_VALUE_SIZE_OFFSET -> this.avgValueSize = (Integer) value;\n      default -> throw new UnsupportedOperationException(\"Unsupported stats offset: \" + offset);","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/FieldStatsStruct.java#L177-L213","documentation":"FieldStatsStruct.getOffset maps stat offsets (UPPER_BOUND, TIGHT_BOUNDS, VALUE_COUNT, NULL_VALUE_COUNT, NAN_VALUE_COUNT, AVG_VALUE_SIZE) to field values; an unrecognized offset throws UnsupportedOperationException('Unsupported stats offset: ' + offset). Since offsets come from posToOffset (built from a projected stats struct schema), this indicates the projection contains a field position with no corresponding stats offset.","triggerScenarios":"Calling get(pos, Class) where posToOffset[pos] was computed from a partition/field-stats schema that includes a field outside the known stats offsets — typically a malformed projection produced by StatsUtil when the schema and stats file version disagree.","commonSituations":"Reading a statistics file written by a different Iceberg version whose StatsUtil offsets changed; custom code constructing posToOffset manually; partition fields added in newer spec versions but the reader is older.","solutions":["Ensure the reader and writer Iceberg versions agree on the stats file schema; re-generate the statistics file with the current version.","Verify posToOffset is built by StatsUtil.posToOffset(...) from the same type used to create the FieldStatsStruct, not by custom code.","Print the offending offset and compare against StatsUtil offset constants to identify the unexpected field.","Upgrade Iceberg if the stats file uses a newer schema version than the reader supports."],"exampleFix":"// before: hand-built offset array\nint[] posToOffset = {0, 1, 2, 99}; // 99 is not a known stats offset\n// after: derive offsets from StatsUtil\nint[] posToOffset = StatsUtil.posToOffset(partitionType, statsType);","handlingStrategy":"validation","validationCode":"for (int offset : posToOffset) {\n  if (!StatsUtil.isKnownOffset(offset)) {\n    throw new IllegalArgumentException(\"Unsupported stats offset in projection: \" + offset);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  C v = statsStruct.get(pos, javaClass);\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage().startsWith(\"Unsupported stats offset\")) {\n    // regenerate the statistics projection with the current StatsUtil\n  } else throw e;\n}","preventionTips":["Always build posToOffset via StatsUtil, never manually.","Regenerate stats files when upgrading Iceberg versions.","Match reader version to the writer version of statistics files."],"tags":["statistics","struct","offset","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}