{"record":{"id":"e7395698cf62314a","repo":"apache/beam","slug":"unknown-changelogscantask-type","errorCode":null,"errorMessage":"Unknown ChangelogScanTask type: {}","messagePattern":"Unknown ChangelogScanTask type: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/iceberg/src/main/java/org/apache/beam/sdk/io/iceberg/cdc/CdcReadUtils.java","lineNumber":235,"sourceCode":"    Schema outputSchema =\n        CdcOutputUtils.readSchemaWithRowMetadata(\n            scanConfig.getMetadataColumns(),\n            useProjectedSchema ? scanConfig.getRequiredSchema() : table.schema());\n    switch (task.getType()) {\n      case ADDED_ROWS:\n        DeleteFilter<Record> addedDeletesFilter =\n            genericDeleteFilter(table, outputSchema, dataFilePath, task.getAddedDeletes());\n        return addedDeletesFilter.filter(\n            createReader(task, table, scanConfig, addedDeletesFilter.requiredSchema()));\n      case DELETED_FILE:\n        DeleteFilter<Record> existingDeletesFilter =\n            genericDeleteFilter(table, outputSchema, dataFilePath, task.getExistingDeletes());\n        return existingDeletesFilter.filter(\n            createReader(task, table, scanConfig, existingDeletesFilter.requiredSchema()));\n      case DELETED_ROWS:\n        return deletedRowsForTask(task, table, scanConfig, outputSchema);\n      default:\n        throw new IllegalStateException(\"Unknown ChangelogScanTask type: \" + task.getType());\n    }\n  }\n\n  /**\n   * Builds the reader chain for a {@code DELETED_ROWS} task with row-group pushdown when possible.\n   * This helps the reader skip entire row groups. For unskipped row groups, the reader should still\n   * apply per-record position + equality checks at the row level.\n   *\n   * <p>We use two pushdown strategies, depending on the type of {@link DeleteFile} in the task\n   * (Position Delete vs. Equality Delete). The two strategies can be combined if both {@link\n   * DeleteFile} types are present.\n   *\n   * <ol>\n   *   <li><b>Byte-range pushdown for Position Deletes:</b> pre-load the {@link\n   *       PositionDeleteIndex}, read the Parquet footer, and compute a single contiguous byte range\n   *       covering the row groups that contain at least one deleted position.\n   *   <li><b>IN-expression pushdown for Equality Deletes:</b> build an Iceberg {@code IN}\n   *       expression and pass it as a Parquet residual so the metrics row-group filter can skip","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/iceberg/src/main/java/org/apache/beam/sdk/io/iceberg/cdc/CdcReadUtils.java#L217-L253","documentation":"CdcReadUtils.changelogRecordsForTask dispatches each Iceberg ChangelogScanTask to a handler based on task.getType(); the implemented cases do not cover every task type. When a task of an unrecognized type arrives, the default branch throws IllegalStateException.","triggerScenarios":"An incremental/changelog scan on an Iceberg table returns a ChangelogScanTask subtype not handled by this reader version (e.g. a newer Iceberg task type like a new delete-kind task), reaching changelogRecordsForTask during CdcRead read expansion.","commonSituations":"Version mismatch between the Iceberg runtime library and the Beam CDC connector (new Iceberg introduces a task type the connector does not know); reading a table written by newer Iceberg features (e.g. new delete file formats).","solutions":["Align the org.apache.iceberg runtime version with the version the Beam connector was built against (upgrade the connector or pin Iceberg).","Avoid enabling newer Iceberg table features (unsupported delete formats) on tables read by this pipeline.","Patch CdcReadUtils to handle the new task type and rebuild the connector.","Inspect task.getType() in logs to identify the exact unhandled type and file an issue upstream."],"exampleFix":"// before\n<dependency><groupId>org.apache.iceberg</groupId><artifactId>iceberg-core</artifactId><version>1.7.0</version></dependency> // connector built for 1.5.x\n// after\n<dependency><groupId>org.apache.iceberg</groupId><artifactId>iceberg-core</artifactId><version>1.5.2</version></dependency>","handlingStrategy":"try-catch","validationCode":"// pre-flight: verify iceberg runtime matches connector expectation\n// e.g. assert CdcReadUtils handles all ChangelogScanTask types present in your scan\nSet<String> handled = Set.of(\"ADDED_ROWS\", \"DELETED_DATA_FILE\", \"DELETED_ROWS\");\nif (!handled.contains(taskType)) throw new IllegalStateException(\"Unhandled task type: \" + taskType);","typeGuard":"boolean isHandledTask(ChangelogScanTask t) {\n  return t instanceof AddedRowsScanTask || t instanceof DeletedDataFileScanTask || t instanceof DeletedRowsScanTask;\n}","tryCatchPattern":"try {\n  return changelogRecordsForTask(task, table, cfg, schema);\n} catch (IllegalStateException e) {\n  if (e.getMessage().startsWith(\"Unknown ChangelogScanTask type\")) {\n    throw new IllegalStateException(\"Upgrade Beam Iceberg connector to support task: \" + task.getType(), e);\n  }\n  throw e;\n}","preventionTips":["Pin org.apache.iceberg to the connector's tested version.","Avoid enabling untested Iceberg table features on scanned tables.","De-duplicate iceberg-core versions on the classpath."],"tags":["java","iceberg","cdc","version-mismatch"],"backgroundTag":"invalid-enum-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}