diff --git a/pyiceberg/table/__init__.py b/pyiceberg/table/__init__.py index 8d79472af5..73c435f07f 100644 --- a/pyiceberg/table/__init__.py +++ b/pyiceberg/table/__init__.py @@ -2490,6 +2490,8 @@ def _plan_files_local(self) -> Iterable[FileScanTask]: """Plan files locally by reading manifests.""" snapshot = self.snapshot() if not snapshot: + if self.snapshot_id is not None: + raise ValueError(f"Snapshot not found: {self.snapshot_id}") return [] return self._manifest_planner.plan_files(snapshot.manifests(self.io)) diff --git a/tests/table/test_init.py b/tests/table/test_init.py index f6b984f1a3..ff7ecd7c37 100644 --- a/tests/table/test_init.py +++ b/tests/table/test_init.py @@ -314,6 +314,17 @@ def test_table_scan_missing_snapshot_zero(table_v2: Table) -> None: assert table_v2.scan(snapshot_id=0).snapshot() is None +def test_table_scan_plan_files_missing_snapshot(table_v2: Table) -> None: + # table_v2 has no snapshot with id 0, so planning raises the same error as projection() and to_arrow() + scan = table_v2.scan(snapshot_id=0) + + with pytest.raises(ValueError, match="Snapshot not found: 0"): + scan.plan_files() + + with pytest.raises(ValueError, match="Snapshot not found: 0"): + scan.count() + + @pytest.mark.parametrize("snapshot_id", [0, 3051729675574597004]) def test_table_scan_ref_cannot_override_snapshot(table_v2: Table, snapshot_id: int) -> None: with pytest.raises(ValueError, match=f"Cannot override ref, already set snapshot id={snapshot_id}"):