{"record":{"id":"0a070b4a8008a5c9","repo":"apache/iceberg","slug":"cannot-find-a-partition-spec-in-iceberg-table-s-t-0a070b","errorCode":null,"errorMessage":"Cannot find a partition spec in Iceberg table %s that matches the partition columns (%s) in input table","messagePattern":"Cannot find a partition spec in Iceberg table (.+?) that matches the partition columns \\((.+?)\\) in input table","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkTableUtil.java","lineNumber":1044,"sourceCode":"        partitionNames.stream()\n            .map(name -> name.toLowerCase(Locale.ROOT))\n            .collect(Collectors.toList());\n    for (PartitionSpec icebergSpec : icebergTable.specs().values()) {\n      boolean allIdentity =\n          icebergSpec.fields().stream().allMatch(field -> field.transform().isIdentity());\n      if (allIdentity) {\n        List<String> icebergPartNames =\n            icebergSpec.fields().stream()\n                .map(PartitionField::name)\n                .map(name -> name.toLowerCase(Locale.ROOT))\n                .collect(Collectors.toList());\n        if (icebergPartNames.equals(partitionNamesLower)) {\n          return icebergSpec;\n        }\n      }\n    }\n\n    throw new IllegalArgumentException(\n        String.format(\n            \"Cannot find a partition spec in Iceberg table %s that matches the partition\"\n                + \" columns (%s) in input table\",\n            icebergTable, partitionNames));\n  }\n\n  /**\n   * Returns the first partition spec in an IcebergTable that shares the same names and ordering as\n   * the partition columns in a given Spark Table. Throws an error if not found\n   */\n  private static PartitionSpec findCompatibleSpec(\n      Table icebergTable, SparkSession spark, String sparkTable) throws AnalysisException {\n    List<String> parts = Lists.newArrayList(Splitter.on('.').limit(2).split(sparkTable));\n    String db = parts.size() == 1 ? \"default\" : parts.get(0);\n    String table = parts.get(parts.size() == 1 ? 0 : 1);\n\n    List<String> sparkPartNames =\n        spark.catalog().listColumns(db, table).collectAsList().stream()","sourceCodeStart":1026,"sourceCodeEnd":1062,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkTableUtil.java#L1026-L1062","documentation":"SparkTableUtil.importSparkTable / partition-spec matching requires the Iceberg table's partition spec to cover exactly the same partition columns as the Spark (Hive) source table. When no Iceberg spec's partition-field names (lowercased) equal the input table's partition column set, this IllegalArgumentException is thrown rather than silently mis-importing partitioned data.","triggerScenarios":"Calling SparkTableUtil.importSparkTable / getPartitions with a source Spark table whose partition columns do not exactly match any partition spec of the target Iceberg table (extra, missing, reordered, or differently named columns).","commonSituations":"Migrating a Hive table to Iceberg when the target Iceberg table was created with different partition columns (e.g. date vs day transform, different column name, unpartitioned target); typos in partition column names; case differences combined with renamed columns.","solutions":["Recreate the Iceberg table with a partition spec whose partition columns exactly match the source table's partition columns","Drop/rename partitions in the source or alter the target spec so the column name sets match exactly (names are compared lowercased)","If partitioning differences are intentional, import the data manually (e.g. via Spark writes) instead of SparkTableUtil's partition-spec matching path"],"exampleFix":"// before: Iceberg table partitioned by day(ts) but Hive table partitioned by column 'dt'\nString.create(...)\n// after: create Iceberg table partitioned by identity(dt)\nTable table = catalog.createTable(ident, schema, PartitionSpec.builderFor(schema).identity(\"dt\").build());","handlingStrategy":"validation","validationCode":"Set<String> src = sourcePartitionCols.stream().map(c -> c.toLowerCase(Locale.ROOT)).collect(Collectors.toSet());\nSet<String> target = table.spec().partitionType().fields().stream().map(f -> f.name().toLowerCase(Locale.ROOT)).collect(Collectors.toSet());\nif (!src.equals(target)) throw new IllegalStateException(\"Partition columns differ: \" + src + \" vs \" + target);","typeGuard":null,"tryCatchPattern":"try { SparkTableUtil.importSparkTable(sparkSession, sourceTable, table, stagingDir); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"Cannot find a partition spec\")) { /* recreate target with matching spec */ } throw e; }","preventionTips":["Create the Iceberg target with identity partitions on exactly the source table's partition columns","Compare partition column names (case-insensitively) before importing","Avoid transform-based specs on the target if you plan to import via SparkTableUtil from a Hive table"],"tags":["spark","migration","partitioning","import"],"backgroundTag":"resource-not-found","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"}