{"record":{"id":"80f9f8f1a03c277c","repo":"apache/iceberg","slug":"cannot-convert-nested-accessor-to-position","errorCode":null,"errorMessage":"Cannot convert nested accessor to position","messagePattern":"Cannot convert nested accessor to position","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/org/apache/iceberg/Accessors.java","lineNumber":51,"sourceCode":" *  |-- a: struct (nullable = false)\n *  |    |-- b: struct (nullable = false)\n *  |        | -- c: string (containsNull = false)\n * </pre>\n *\n * Then we will use Position3Accessor to access nested field 'c'. It can be accessed like this:\n * {@code row.get(p0, StructLike.class).get(p1, StructLike.class).get(p2, javaClass)}. Commonly,\n * Nested fields with depth=1 or 2 or 3 are the fields that will be accessed frequently, so this\n * optimization will help to access this kind of schema. For schema whose depth is deeper than 3,\n * then we will use the {@link WrappedPositionAccessor} to access recursively.\n */\npublic class Accessors {\n  private Accessors() {}\n\n  public static Integer toPosition(Accessor<StructLike> accessor) {\n    if (accessor instanceof PositionAccessor) {\n      return ((PositionAccessor) accessor).position();\n    }\n    throw new IllegalArgumentException(\"Cannot convert nested accessor to position\");\n  }\n\n  static Map<Integer, Accessor<StructLike>> forSchema(Schema schema) {\n    return TypeUtil.visit(schema, new BuildPositionAccessors());\n  }\n\n  private static class PositionAccessor implements Accessor<StructLike> {\n    private final int position;\n    private final Type type;\n    private final Class<?> javaClass;\n\n    PositionAccessor(int pos, Type type) {\n      this.position = pos;\n      this.type = type;\n      this.javaClass = type.typeId().javaClass();\n    }\n\n    @Override","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/api/src/main/java/org/apache/iceberg/Accessors.java#L33-L69","documentation":"Accessors.toPosition() converts an accessor to an integer position only when it is a PositionAccessor. Nested accessors (e.g. accessing a field inside a nested struct) cannot be reduced to a single top-level position, so this IllegalArgumentException is thrown. It guards against misuse of the accessor API.","triggerScenarios":"Passing an accessor obtained for a nested field (produced by visiting a schema with nested struct fields) into Accessors.toPosition(), e.g. when code assumes all accessors are positional.","commonSituations":"Writing generic code over schema accessors that handles flat schemas but encounters nested types (struct-in-struct, list of structs); older code paths after schemas gained nested fields.","solutions":["Only call toPosition() for top-level (non-nested) field accessors; check instanceof Accessors.PositionAccessor first.","For nested fields, navigate the accessor chain yourself instead of asking for a single position.","If your schema must be flat, flatten it (e.g. schema case-aware access via projected schema) before building accessors."],"exampleFix":"// before\nInteger pos = Accessors.toPosition(accessor);\n\n// after\nif (accessor instanceof Accessors.PositionAccessor) {\n  Integer pos = ((Accessors.PositionAccessor) accessor).position();\n} else {\n  // handle nested accessor path\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"if (accessor instanceof Accessors.PositionAccessor) {\n  int pos = ((Accessors.PositionAccessor) accessor).position();\n} else {\n  // nested accessor: walk its nested path instead of toPosition()\n}","tryCatchPattern":"try {\n  Integer pos = Accessors.toPosition(accessor);\n} catch (IllegalArgumentException e) {\n  // fall back to nested-accessor handling\n}","preventionTips":["Check instanceof PositionAccessor before calling toPosition().","Design code paths over accessors to handle nested struct fields.","Add tests with nested schemas to catch non-positional accessors."],"tags":["schema","accessor","nested-types"],"backgroundTag":"invalid-argument-value","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"}