{"record":{"id":"cdd9374f5bc3eb05","repo":"apache/iceberg","slug":"cannot-delete-element-type-from-list","errorCode":null,"errorMessage":"Cannot delete element type from list: ","messagePattern":"Cannot delete element type from list: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/SchemaUpdate.java","lineNumber":695,"sourceCode":"        // if either collection is non-null, then this must be a struct type. try to apply the\n        // changes\n        List<Types.NestedField> fields =\n            addAndMoveFields(fieldResult.asStructType().fields(), newFields, columnsToMove);\n        if (fields != null) {\n          return Types.StructType.of(fields);\n        }\n      }\n\n      return fieldResult;\n    }\n\n    @Override\n    public Type list(Types.ListType list, Type elementResult) {\n      // use field to apply updates\n      Types.NestedField elementField = list.fields().get(0);\n      Type elementType = field(elementField, elementResult);\n      if (elementType == null) {\n        throw new IllegalArgumentException(\"Cannot delete element type from list: \" + list);\n      }\n\n      Types.NestedField elementUpdate = updates.get(elementField.fieldId());\n      boolean isElementOptional =\n          elementUpdate != null ? elementUpdate.isOptional() : list.isElementOptional();\n\n      if (isElementOptional == elementField.isOptional() && list.elementType() == elementType) {\n        return list;\n      }\n\n      if (isElementOptional) {\n        return Types.ListType.ofOptional(list.elementId(), elementType);\n      } else {\n        return Types.ListType.ofRequired(list.elementId(), elementType);\n      }\n    }\n\n    @Override","sourceCodeStart":677,"sourceCodeEnd":713,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/SchemaUpdate.java#L677-L713","documentation":"During SchemaUpdate.apply, a TypeUtil visitor rebuilds the schema; for a list type it recursively resolves the element type via field(). If field() returns null — meaning the element field is being deleted (it is in the deletes set) — this IllegalArgumentException is thrown, because deleting a list's element type outright is not a supported schema update.","triggerScenarios":"Calling schema.update(...) / updateSchema.delete(elementFieldId) where elementFieldId is the list element field's ID (the nested field id of the list element), attempting to delete the element of a list column.","commonSituations":"Tooling that enumerates all nested field IDs and issues deletes for them, accidentally including list element IDs; users intending to drop the whole list column but targeting the element field id instead of the column's top-level id.","solutions":["Delete the top-level list column by its own field ID instead of the element field ID","If the intent is to replace the element type, use updateSchema.updateColumn(...)/addElement/requireElement rather than delete","Filter generated delete sets to exclude nested list element field IDs"],"exampleFix":"// before\nint elementId = listType.fields().get(0).fieldId();\nupdateSchema.delete(elementId); // throws\n// after\nupdateSchema.delete(listColumnFieldId); // delete the list column itself","handlingStrategy":"validation","validationCode":"Set<Integer> deletable = new HashSet<>();\nschema.columns().forEach(f -> collectDeletableIds(f, deletable));\nstatic void collectDeletableIds(Types.NestedField f, Set<Integer> out) {\n  out.add(f.fieldId());\n  if (f.type() instanceof Types.StructType) f.type().asStructType().fields().forEach(c -> collectDeletableIds(c, out));\n  // note: list element and map key/value ids are NOT added\n}","typeGuard":"static boolean isListElementId(Schema schema, int fieldId) {\n  return schema.columns().stream().flatMap(f -> nestedTypes(f.type()).stream())\n      .anyMatch(t -> t instanceof Types.ListType && t.asListType().fields().get(0).fieldId() == fieldId);\n}","tryCatchPattern":"try {\n  updateSchema.apply();\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().startsWith(\"Cannot delete element type\")) throw new IllegalStateException(\"Delete the list column, not its element field\", e);\n  throw e;\n}","preventionTips":["Delete columns by their top-level field ID, never by nested element/key/value IDs","When enumerating nested IDs for bulk operations, exclude list element, map key and map value IDs","Use Schema.findField(name) to resolve intended columns rather than raw ID math"],"tags":["schema","schema-evolution","validation"],"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"}