{"record":{"id":"74d3e6552fa7f858","repo":"apache/iceberg","slug":"invalid-primary-key-s-a-primary-key-must-not-c-74d3e6","errorCode":null,"errorMessage":"Invalid primary key '%s'. A primary key must not contain duplicate columns. Found: %s","messagePattern":"Invalid primary key '(.+?)'\\. A primary key must not contain duplicate columns\\. Found: (.+?)","errorType":"validation","errorClass":"org.apache.flink.table.api.ValidationException","httpStatus":null,"severity":"error","filePath":"flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/FlinkSchemaUtil.java","lineNumber":349,"sourceCode":"    return new ResolvedSchema(columns, Collections.emptyList(), uniqueConstraint);\n  }\n\n  /**\n   * Copied from\n   * org.apache.flink.table.catalog.DefaultSchemaResolver#validatePrimaryKey(org.apache.flink.table.catalog.UniqueConstraint,\n   * java.util.List)\n   */\n  private static void validatePrimaryKey(UniqueConstraint primaryKey, List<Column> columns) {\n    final Map<String, Column> columnsByNameLookup =\n        columns.stream().collect(Collectors.toMap(Column::getName, Function.identity()));\n\n    final Set<String> duplicateColumns =\n        primaryKey.getColumns().stream()\n            .filter(name -> Collections.frequency(primaryKey.getColumns(), name) > 1)\n            .collect(Collectors.toSet());\n\n    if (!duplicateColumns.isEmpty()) {\n      throw new ValidationException(\n          String.format(\n              \"Invalid primary key '%s'. A primary key must not contain duplicate columns. Found: %s\",\n              primaryKey.getName(), duplicateColumns));\n    }\n\n    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.\",","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/FlinkSchemaUtil.java#L331-L367","documentation":"FlinkSchemaUtil.validatePrimaryKey rejects a Flink primary key (UniqueConstraint) whose column list contains duplicates. A primary key must uniquely identify rows with a distinct set of columns; duplicates make the constraint invalid, so a ValidationException is thrown naming the duplicated columns.","triggerScenarios":"Defining a Flink table DDL with PRIMARY KEY (a, a, b) or building a ResolvedSchema whose UniqueConstraint lists the same column twice, then converting via FlinkSchemaUtil.toResolvedSchema.","commonSituations":"Programmatic schema construction where key columns are appended from multiple sources without dedup; hand-written DDL typos; SQL builders concatenating key lists.","solutions":["Deduplicate the primary key column list before constructing the schema/constraint","Fix the DDL so each primary key column appears once","Validate uniqueness of key columns in code that assembles schemas dynamically"],"exampleFix":"// before\nList<String> keys = Stream.concat(leftKeys, rightKeys).collect(toList());\n\n// after\nList<String> keys = Stream.concat(leftKeys, rightKeys).distinct().collect(toList());","handlingStrategy":"validation","validationCode":"Set<String> seen = new HashSet<>();\nfor (String c : keyColumns) { if (!seen.add(c)) throw new IllegalArgumentException(\"duplicate key column: \" + c); }","typeGuard":null,"tryCatchPattern":"try { FlinkSchemaUtil.toResolvedSchema(schema); } catch (ValidationException e) { /* inspect primary key definition */ }","preventionTips":["Deduplicate key column lists when building schemas programmatically","Review DDL primary key clauses for repeats","Add schema assembly tests that check key uniqueness"],"tags":["flink","schema","primary-key","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"}