{"record":{"id":"1e930d8f14733f65","repo":"apache/iceberg","slug":"cannot-update-map-keys","errorCode":null,"errorMessage":"Cannot update map keys: ","messagePattern":"Cannot update map keys: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/SchemaUpdate.java","lineNumber":720,"sourceCode":"      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\n    public Type map(Types.MapType map, Type kResult, Type valueResult) {\n      // if any updates are intended for the key, throw an exception\n      int keyId = map.fields().get(0).fieldId();\n      if (deletes.contains(keyId)) {\n        throw new IllegalArgumentException(\"Cannot delete map keys: \" + map);\n      } else if (updates.containsKey(keyId)) {\n        throw new IllegalArgumentException(\"Cannot update map keys: \" + map);\n      } else if (parentToAddedIds.containsKey(keyId)) {\n        throw new IllegalArgumentException(\"Cannot add fields to map keys: \" + map);\n      } else if (!map.keyType().equals(kResult)) {\n        throw new IllegalArgumentException(\"Cannot alter map keys: \" + map);\n      }\n\n      // use field to apply updates to the value\n      Types.NestedField valueField = map.fields().get(1);\n      Type valueType = field(valueField, valueResult);\n      if (valueType == null) {\n        throw new IllegalArgumentException(\"Cannot delete value type from map: \" + map);\n      }\n\n      Types.NestedField valueUpdate = updates.get(valueField.fieldId());\n      boolean isValueOptional =\n          valueUpdate != null ? valueUpdate.isOptional() : map.isValueOptional();\n\n      if (isValueOptional == map.isValueOptional() && map.valueType() == valueType) {","sourceCodeStart":702,"sourceCodeEnd":738,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/SchemaUpdate.java#L702-L738","documentation":"Map keys in Iceberg are immutable identity components of the map type; the schema evolution rules prohibit updating (renaming, retyping, re-required-ness) the hidden key field. If SchemaUpdate.apply finds the map key's field ID in the updates map, it throws this IllegalArgumentException.","triggerScenarios":"Calling updateSchema.updateColumn(keyFieldId, ...) / requireOptional(keyFieldId) / rename(keyFieldId, ...) where the target ID is a map key's internal field ID.","commonSituations":"Bulk update scripts applying type-widening or optionality changes to every nested field ID, accidentally including map key IDs; attempts to 'widen' key types via generic update tooling.","solutions":["Do not update map key fields; rebuild the map column with a new key type by dropping and re-adding the column (acknowledging data rewrite semantics)","Restrict updateColumn/require calls to non-key field IDs"],"exampleFix":"// before\nupdateSchema.updateColumn(mapKeyFieldId, Types.LongType.get()); // throws\n// after\nupdateSchema.delete(mapColumn.fieldId());\nupdateSchema.addColumn(parent, name, Types.MapType.ofOptional(keyId, valueId, Types.LongType.get(), valueType));","handlingStrategy":"validation","validationCode":"Types.MapType map = ...;\nint keyId = map.fields().get(0).fieldId();\nif (requestedUpdates.containsKey(keyId)) throw new IllegalArgumentException(\"Map keys cannot be updated; rebuild the map column instead\");","typeGuard":"static boolean updateTouchesMapKey(UpdateSchema update, Types.MapType map) {\n  int keyId = map.fields().get(0).fieldId();\n  return update.appliedUpdates().stream().anyMatch(u -> u instanceof UpdateColumn && ((UpdateColumn) u).fieldId() == keyId);\n}","tryCatchPattern":"try {\n  updateSchema.apply();\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().startsWith(\"Cannot update map keys\")) throw new IllegalStateException(\"Drop and re-add the map with the desired key type (requires data rewrite)\", e);\n  throw e;\n}","preventionTips":["Exclude map key IDs from bulk updateColumn/requireOptional/rename sweeps","To change a key type, drop and re-add the whole map column","Treat key field IDs (and value IDs) as reserved and untouchable"],"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"}