Summary
to_geotiff(..., nodata=True) is accepted without validation. build_geo_tags then writes the GDAL_NODATA tag as the literal string "True" via str(nodata). On read, that string cannot be parsed as numeric, so open_geotiff returns a DataArray with empty attrs (no nodata key) and does not mask anything. The user gets no warning and no error: the typo silently breaks the round-trip.
Reproduction
import numpy as np, xarray as xr
from xrspatial.geotiff import to_geotiff, open_geotiff
da = xr.DataArray(np.zeros((4, 4), dtype='uint8'))
to_geotiff(da, "/tmp/rockout_nodata_bool.tif", nodata=True)
r = open_geotiff("/tmp/rockout_nodata_bool.tif")
print(repr(r.attrs.get('nodata'))) # None
Inspecting the raw file confirms the literal bytes True were written into the GDAL_NODATA tag.
Affected code
xrspatial/geotiff/_geotags.py:1155-1157:
# GDAL_NODATA
if nodata is not None:
tags[TAG_GDAL_NODATA] = str(nodata)
bool is a subclass of int in Python, so it slips past any later isinstance(nodata, (int, float)) guard. str(True) returns "True", which is not a numeric token that GDAL or this module's reader recognises.
Fix direction
Reject bool and np.bool_ early at the writer entry point (to_geotiff) with a TypeError. The user almost certainly meant True as a typo for a real sentinel value; normalising True -> 1 would hide the mistake. Match the pattern already used in _reader.py and _vrt.py:
if isinstance(nodata, (bool, np.bool_)):
raise TypeError(f"nodata must be numeric (int or float), got {nodata!r}")
A defensive copy of the same check inside build_geo_tags keeps the lower-level builder safe against future callers.
Summary
to_geotiff(..., nodata=True)is accepted without validation.build_geo_tagsthen writes the GDAL_NODATA tag as the literal string"True"viastr(nodata). On read, that string cannot be parsed as numeric, soopen_geotiffreturns a DataArray with emptyattrs(nonodatakey) and does not mask anything. The user gets no warning and no error: the typo silently breaks the round-trip.Reproduction
Inspecting the raw file confirms the literal bytes
Truewere written into the GDAL_NODATA tag.Affected code
xrspatial/geotiff/_geotags.py:1155-1157:boolis a subclass ofintin Python, so it slips past any laterisinstance(nodata, (int, float))guard.str(True)returns"True", which is not a numeric token that GDAL or this module's reader recognises.Fix direction
Reject
boolandnp.bool_early at the writer entry point (to_geotiff) with aTypeError. The user almost certainly meantTrueas a typo for a real sentinel value; normalisingTrue -> 1would hide the mistake. Match the pattern already used in_reader.pyand_vrt.py:A defensive copy of the same check inside
build_geo_tagskeeps the lower-level builder safe against future callers.