{"record":{"id":"8518819554321312","repo":"apache/iceberg","slug":"invalid-primary-key-s-column-s-is-nullable-851881","errorCode":null,"errorMessage":"Invalid primary key '%s'. Column '%s' is nullable.","messagePattern":"Invalid primary key '(.+?)'\\. Column '(.+?)' is nullable\\.","errorType":"validation","errorClass":"org.apache.flink.table.api.ValidationException","httpStatus":null,"severity":"error","filePath":"flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/FlinkSchemaUtil.java","lineNumber":373,"sourceCode":"    for (String columnName : primaryKey.getColumns()) {\n      Column column = columnsByNameLookup.get(columnName);\n      if (column == null) {\n        throw new ValidationException(\n            String.format(\n                \"Invalid primary key '%s'. Column '%s' does not exist.\",\n                primaryKey.getName(), columnName));\n      }\n\n      if (!column.isPhysical()) {\n        throw new ValidationException(\n            String.format(\n                \"Invalid primary key '%s'. Column '%s' is not a physical column.\",\n                primaryKey.getName(), columnName));\n      }\n\n      final LogicalType columnType = column.getDataType().getLogicalType();\n      if (columnType.isNullable()) {\n        throw new ValidationException(\n            String.format(\n                \"Invalid primary key '%s'. Column '%s' is nullable.\",\n                primaryKey.getName(), columnName));\n      }\n    }\n  }\n}\n","sourceCodeStart":355,"sourceCodeEnd":381,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/FlinkSchemaUtil.java#L355-L381","documentation":"validatePrimaryKey checks that each primary key column's logical type is non-nullable; a nullable key column makes the row identifier meaningless for upserts. It throws ValidationException naming the key and the nullable column.","triggerScenarios":"toResolvedSchema with a PRIMARY KEY whose column type is nullable — e.g. a column declared without NOT NULL but included in PRIMARY KEY (id) NOT ENFORCED.","commonSituations":"Forgetting NOT NULL on key columns in DDL; building a DataTypes.RowField for the key column without NOT NULL; schemas imported from sources that allow nulls.","solutions":["Declare the primary key column as NOT NULL in the schema/DDL.","When building fields programmatically, wrap the type with DataTypes.FIELD(..., type.NOT_NULL()).","Pick a different non-nullable column (or a combination of such) as the key."],"exampleFix":"// before\nid INT, name STRING, PRIMARY KEY (id) NOT ENFORCED\n// after\nid INT NOT NULL, name STRING, PRIMARY KEY (id) NOT ENFORCED","handlingStrategy":"validation","validationCode":"for (String c : primaryKey.getColumns()) {\n  Column col = schema.getColumn(c).orElseThrow();\n  if (col.getDataType().getLogicalType().isNullable()) {\n    throw new IllegalArgumentException(\"PK column must be NOT NULL: \" + c);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  ResolvedSchema rs = FlinkSchemaUtil.toResolvedSchema(schema);\n} catch (ValidationException e) {\n  // message names the nullable column; add NOT NULL\n}","preventionTips":["Always declare key columns NOT NULL in DDL.","In programmatic schemas use type.NOT_NULL() on key fields.","Validate key column nullability in schema unit tests."],"tags":["flink","schema","primary-key","nullable","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}