{"record":{"id":"b9488132987c8bb4","repo":"risingwavelabs/risingwave","slug":"iceberg-scan-limit-can-only-be-planned-for-data-sc","errorCode":null,"errorMessage":"Iceberg scan limit can only be planned for data scan tasks","messagePattern":"Iceberg scan limit can only be planned for data scan tasks","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/connector/src/source/iceberg/planner.rs","lineNumber":671,"sourceCode":"    ) -> Self {\n        Self {\n            chunk_size,\n            need_seq_num,\n            need_file_path_and_pos,\n            handle_delete_files,\n        }\n    }\n}\n\nimpl IcebergScanTaskPlanner {\n    pub fn plan_splits(\n        task: IcebergFileScanTask,\n        split_num: usize,\n        limit: Option<u64>,\n    ) -> ConnectorResult<Vec<IcebergSplit>> {\n        let scan_type = task.scan_type();\n        if limit.is_some() && scan_type != IcebergScanType::DataScan {\n            bail!(\"Iceberg scan limit can only be planned for data scan tasks\");\n        }\n\n        let task_batches = Self::plan_task_batches(\n            task,\n            split_num,\n            limit,\n            IcebergScanTaskBatchMode::PreserveParallelism,\n        );\n\n        task_batches\n            .into_iter()\n            .enumerate()\n            .map(|(id, tasks)| {\n                Ok(IcebergSplit {\n                    split_id: id.try_into().unwrap(),\n                    task: IcebergFileScanTask::from_tasks(scan_type, tasks)?,\n                    limit,\n                })","sourceCodeStart":653,"sourceCodeEnd":689,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/connector/src/source/iceberg/planner.rs#L653-L689","documentation":"`plan_splits` allows an optional row `limit` to be planned only when the task is a plain DataScan. Limit pushdown cannot be applied to equality-delete or position-delete scans because reading delete files requires scanning all applicable deletes; applying a limit would produce incorrect results, so the code bails.","triggerScenarios":"`plan_splits` (called during Iceberg split planning) receiving `limit: Some(n)` while `task.scan_type() != IcebergScanType::DataScan` — i.e. a LIMIT query planned against a merge-on-read table with equality or position delete files.","commonSituations":"Running `SELECT ... LIMIT n` on an Iceberg table that has pending delete files; a planner regression that pushes a limit into delete scans; query with filters hitting rows covered by MoR deletes.","solutions":["Remove/compaction the delete files first (rewrite/compact the table) so the scan becomes a DataScan and limit pushdown is allowed.","Avoid LIMIT pushdown for that query (e.g. rewrite the query or run without relying on limit optimization).","Use copy-on-write delete mode so deletes are merged into data files and scans stay DataScan.","If it is a planner bug, gate limit pushdown on scan_type before calling plan_splits."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let limit = if task.scan_type() == IcebergScanType::DataScan { limit } else { None };\nlet splits = planner.plan_splits(task, split_num, limit)?;","typeGuard":"fn limit_allowed(t: &IcebergScanType, limit: Option<u64>) -> bool {\n    limit.is_none() || *t == IcebergScanType::DataScan\n}","tryCatchPattern":"match plan_splits(task, split_num, limit) {\n    Err(e) if e.to_string().contains(\"scan limit can only be planned for data scan\") => {\n        // compact deletes or retry without limit pushdown\n    }\n    r => r,\n}","preventionTips":["Only push LIMIT into DataScan tasks","Compact/rewrite MoR delete files before relying on limit optimization","Prefer copy-on-write tables for limit-heavy workloads"],"tags":["rust","iceberg","limit-pushdown","merge-on-read"],"backgroundTag":"invalid-state-transition","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}