From bca6ea2a722edec32a5a5630303a246f93690cab Mon Sep 17 00:00:00 2001 From: Brendan Collins Date: Fri, 15 May 2026 12:54:49 -0700 Subject: [PATCH] geotiff: skip require_transform fail-closed when coords use int no-georef sentinel PR #1945 added require_transform_for_georeferenced to fail closed when a DataArray carries spatial coords but no transform could be derived. PR #1949 (merged the same day) made coords_to_transform return None for integer-dtype coords because those are the read-side no-georef sentinel that open_geotiff emits for files without GeoTIFF tags. The combination breaks any round-trip that reads a non-georef TIFF and writes it back: coords_to_transform returns None on the int coords, then require_transform_for_georeferenced raises ValueError. Mirror the int-dtype short-circuit in the fail-closed guard so the sentinel path stays silent and only float-coord 1x1 inputs trip the error. --- xrspatial/geotiff/_coords.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xrspatial/geotiff/_coords.py b/xrspatial/geotiff/_coords.py index c1e4493a..c740e933 100644 --- a/xrspatial/geotiff/_coords.py +++ b/xrspatial/geotiff/_coords.py @@ -262,6 +262,17 @@ def require_transform_for_georeferenced( ydim = da.dims[-2] xdim = da.dims[-1] if xdim in da.coords and ydim in da.coords: + # Integer-dtype coords are the read-side no-georef sentinel + # (see #1949 + ``coords_to_transform``): the reader emits + # ``np.arange(N, dtype=np.int64)`` for files without GeoTIFF + # tags. Those callers are explicitly *not* requesting a + # georeferenced output, so the fail-closed guard must not fire + # on them. Mirrors the same short-circuit in + # ``coords_to_transform``. + x = da.coords[xdim].values + y = da.coords[ydim].values + if x.dtype.kind in ('i', 'u') or y.dtype.kind in ('i', 'u'): + return raise ValueError( f"Cannot infer GeoTIFF transform from a " f"{tuple(da.sizes.values())} array with spatial coords on "