Describe the bug
to_geotiff(..., cog=True, tiled=False, tile_size=-1) hangs the writer.
tile_size validation in xrspatial/geotiff/_writers/eager.py:342 only runs when tiled=True, but the COG path in xrspatial/geotiff/_writer.py:490 reads tile_size to auto-generate overviews regardless of tiled. With a negative tile_size, the auto-overview loop's oh > tile_size and ow > tile_size stays true once oh, ow halve to 0, and the inner if oh > 0 and ow > 0 guard prevents the level list from growing. The loop never exits.
I confirmed the hang with a 3-second timeout on the reproducer below.
Expected behavior
to_geotiff(..., cog=True, tile_size=<=0) should raise a ValueError up front, regardless of tiled. The COG contract was promoted to stable in PR #2300; an infinite loop on a bad input is a validation-side contract violation.
Reproducer
import numpy as np
import xarray as xr
from xrspatial.geotiff import to_geotiff
data = xr.DataArray(np.ones((64, 64), dtype="float32"), dims=("y", "x"))
# Hangs forever (negative tile_size, cog=True, tiled=False):
to_geotiff(data, "/tmp/hang.tif", cog=True, tiled=False, tile_size=-1)
Fix shape
- Validate
tile_size at the public boundary so it cannot be <=0 when cog=True, regardless of tiled. Reject with a ValueError matching the existing validator wording.
- Defense in depth: guard the auto-overview loop in
_writer.py:490 so it cannot run forever if a bad tile_size reaches it (require oh, ow > 0 to continue, or pre-check tile_size > 0).
- Regression test exercises
cog=True with a bad tile_size and asserts the writer raises within a short timeout. Covers both tiled=True and tiled=False.
Describe the bug
to_geotiff(..., cog=True, tiled=False, tile_size=-1)hangs the writer.tile_sizevalidation inxrspatial/geotiff/_writers/eager.py:342only runs whentiled=True, but the COG path inxrspatial/geotiff/_writer.py:490readstile_sizeto auto-generate overviews regardless oftiled. With a negativetile_size, the auto-overview loop'soh > tile_size and ow > tile_sizestays true onceoh, owhalve to 0, and the innerif oh > 0 and ow > 0guard prevents the level list from growing. The loop never exits.I confirmed the hang with a 3-second timeout on the reproducer below.
Expected behavior
to_geotiff(..., cog=True, tile_size=<=0)should raise aValueErrorup front, regardless oftiled. The COG contract was promoted to stable in PR #2300; an infinite loop on a bad input is a validation-side contract violation.Reproducer
Fix shape
tile_sizeat the public boundary so it cannot be<=0whencog=True, regardless oftiled. Reject with aValueErrormatching the existing validator wording._writer.py:490so it cannot run forever if a badtile_sizereaches it (requireoh, ow > 0to continue, or pre-checktile_size > 0).cog=Truewith a badtile_sizeand asserts the writer raises within a short timeout. Covers bothtiled=Trueandtiled=False.