Skip to content

geotiff: to_geotiff(nodata=True) silently writes unparseable "True" tag #1911

@brendancol

Description

@brendancol

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinginput-validationInput validation and error messages

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions