{"record":{"id":"ea498694a85f5fd2","repo":"apache/iceberg","slug":"cannot-convert-update-requirement-to-json-unrecog","errorCode":null,"errorMessage":"Cannot convert update requirement to json. Unrecognized type: %s","messagePattern":"Cannot convert update requirement to json\\. Unrecognized type: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/UpdateRequirementParser.java","lineNumber":134,"sourceCode":"        break;\n      case ASSERT_LAST_ASSIGNED_PARTITION_ID:\n        writeAssertLastAssignedPartitionId(\n            (UpdateRequirement.AssertLastAssignedPartitionId) updateRequirement, generator);\n        break;\n      case ASSERT_CURRENT_SCHEMA_ID:\n        writeAssertCurrentSchemaId(\n            (UpdateRequirement.AssertCurrentSchemaID) updateRequirement, generator);\n        break;\n      case ASSERT_DEFAULT_SPEC_ID:\n        writeAssertDefaultSpecId(\n            (UpdateRequirement.AssertDefaultSpecID) updateRequirement, generator);\n        break;\n      case ASSERT_DEFAULT_SORT_ORDER_ID:\n        writeAssertDefaultSortOrderId(\n            (UpdateRequirement.AssertDefaultSortOrderID) updateRequirement, generator);\n        break;\n      default:\n        throw new IllegalArgumentException(\n            String.format(\n                \"Cannot convert update requirement to json. Unrecognized type: %s\",\n                requirementType));\n    }\n\n    generator.writeEndObject();\n  }\n\n  /**\n   * Read MetadataUpdate from a JSON string.\n   *\n   * @param json a JSON string of a MetadataUpdate\n   * @return a MetadataUpdate object\n   */\n  public static UpdateRequirement fromJson(String json) {\n    return JsonUtil.parse(json, UpdateRequirementParser::fromJson);\n  }\n","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/UpdateRequirementParser.java#L116-L152","documentation":"Thrown by UpdateRequirementParser.toJson when it encounters an UpdateRequirement whose RequirementType is not one of the known cases in its switch. The parser only knows the requirement types defined at its time of compilation; a newer requirement type from a newer Iceberg version (or a custom implementation) cannot be serialized, so it fails fast with IllegalArgumentException rather than writing an incomplete requirement.","triggerScenarios":"Calling UpdateRequirementParser.toJson (directly or via REST catalog client metadata-update serialization) on an UpdateRequirement whose type() is not in {ASSERT_TABLE_UUID, ASSERT_LAST_ASSIGNED_FIELD_ID, ASSERT_CURRENT_SCHEMA_ID, ASSERT_LAST_ASSIGNED_PARTITION_ID, ASSERT_DEFAULT_SPEC_ID, ASSERT_DEFAULT_SORT_ORDER_ID, ASSERT_REF_SNAPSHOT_ID}.","commonSituations":"Mixing Iceberg jar versions — an app built against a newer Iceberg with a new requirement type submits work to a runtime with an older core jar; custom UpdateRequirement implementations passed into the parser; shaded/duplicated iceberg-core classes on the classpath where the parser is older than the requirement classes.","solutions":["Align all Iceberg jars to one version so the parser knows every requirement type in use (check for mixed iceberg-core versions on the classpath).","Check for duplicate/shaded org.apache.iceberg classes (mvn dependency:tree, ensure a single iceberg-core) that cause version skew between parser and requirement classes.","Upgrade iceberg-core on the component performing serialization if a newer requirement type must be supported.","Do not pass custom/unknown UpdateRequirement implementations to the standard parser; extend the parser in a fork only if truly needed."],"exampleFix":"// before (mixed versions: parser predates ASSERT_REF_SNAPSHOT_ID)\nString json = UpdateRequirementParser.toJson(requirement); // throws\n// after: pin one Iceberg version across app and runtime\n// build.gradle: implementation 'org.apache.iceberg:iceberg-core:1.6.1' everywhere\n// (no iceberg-core 1.4 jars left on the classpath)","handlingStrategy":"validation","validationCode":"switch (requirement.type()) {\n  case ASSERT_TABLE_UUID: case ASSERT_LAST_ASSIGNED_FIELD_ID:\n  case ASSERT_CURRENT_SCHEMA_ID: case ASSERT_LAST_ASSIGNED_PARTITION_ID:\n  case ASSERT_DEFAULT_SPEC_ID: case ASSERT_DEFAULT_SORT_ORDER_ID:\n  case ASSERT_REF_SNAPSHOT_ID: break;\n  default: throw new IllegalStateException(\"Requirement not serializable by this Iceberg version: \" + requirement.type());\n}","typeGuard":"boolean serializable(UpdateRequirement r) {\n  return EnumSet.of(RequirementType.ASSERT_TABLE_UUID, RequirementType.ASSERT_LAST_ASSIGNED_FIELD_ID,\n      RequirementType.ASSERT_CURRENT_SCHEMA_ID, RequirementType.ASSERT_LAST_ASSIGNED_PARTITION_ID,\n      RequirementType.ASSERT_DEFAULT_SPEC_ID, RequirementType.ASSERT_DEFAULT_SORT_ORDER_ID,\n      RequirementType.ASSERT_REF_SNAPSHOT_ID).contains(r.type());\n}","tryCatchPattern":"try {\n  String json = UpdateRequirementParser.toJson(requirement);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"Unrecognized type\")) {\n    throw new IllegalStateException(\"Iceberg version skew: upgrade iceberg-core to match requirement type\", e);\n  }\n  throw e;\n}","preventionTips":["Pin a single Iceberg version across app, Spark/Flink runtime, and REST client","Check classpath for duplicate/shaded org.apache.iceberg classes (dependency:tree)","Avoid custom UpdateRequirement implementations with the stock parser","When upgrading one component, upgrade all components that serialize requirements"],"tags":["serialization","json","version-mismatch","iceberg"],"backgroundTag":"json-marshal-failed","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"}