Skip to content

geotiff: reject bool nodata in to_geotiff (#1911)#1917

Merged
brendancol merged 1 commit into
mainfrom
fix-nodata-bool-rejection-2026-05-15
May 15, 2026
Merged

geotiff: reject bool nodata in to_geotiff (#1911)#1917
brendancol merged 1 commit into
mainfrom
fix-nodata-bool-rejection-2026-05-15

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Summary

Fixes #1911.

to_geotiff(..., nodata=True) was accepted without validation, and build_geo_tags then wrote GDAL_NODATA as the literal string "True". The reader cannot parse that as numeric, so open_geotiff silently returned a DataArray with empty attrs and no mask. bool is a subclass of int in Python, so the typo slipped past every downstream isinstance(nodata, (int, float)) guard.

This PR rejects bool and np.bool_ at the to_geotiff entry point with a clear TypeError, matching the pattern already used in _reader.py and _vrt.py. The same check is added inside build_geo_tags so callers that bypass to_geotiff cannot reintroduce the bug.

Files

  • xrspatial/geotiff/_writers/eager.py: bool / np.bool_ guard at the top of to_geotiff
  • xrspatial/geotiff/_geotags.py: same guard inside build_geo_tags (belt-and-braces; uses a local numpy import to avoid adding a new top-level dep)
  • xrspatial/geotiff/tests/test_nodata_bool_rejection_1911.py: new test file

Test plan

  • to_geotiff(..., nodata=True) raises TypeError
  • to_geotiff(..., nodata=False) raises TypeError
  • to_geotiff(..., nodata=np.bool_(True)) raises TypeError
  • to_geotiff(..., nodata=0) still works
  • to_geotiff(..., nodata=0.0) still works
  • to_geotiff(..., nodata=-9999) still works
  • to_geotiff(..., nodata=None) still works (no GDAL_NODATA tag, no nodata attr on read)
  • Numeric nodata round-trips through open_geotiff
  • build_geo_tags(..., nodata=True) raises TypeError
  • Full nodata-related test suite still passes (301 passed, no regressions)

to_geotiff(..., nodata=True) was accepted without validation, and
build_geo_tags then wrote GDAL_NODATA as the literal string "True".
On read, that string cannot be parsed as numeric, so open_geotiff
silently returned a DataArray with empty attrs and no mask. bool is
a subclass of int in Python, so the typo slipped past every
downstream isinstance(nodata, (int, float)) guard.

Reject bool and np.bool_ at the to_geotiff entry point with a clear
TypeError, matching the pattern already used in _reader.py and
_vrt.py. Add the same check inside build_geo_tags so callers that
bypass to_geotiff cannot reintroduce the bug.

Fixes #1911.
Copilot AI review requested due to automatic review settings May 15, 2026 13:25
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label May 15, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes #1911 by preventing to_geotiff(..., nodata=True/False) (and np.bool_) from being accepted and written as the non-numeric GDAL_NODATA string "True"/"False", which previously broke nodata round-trips silently.

Changes:

  • Add an early TypeError guard in to_geotiff rejecting bool / np.bool_ for nodata.
  • Add the same defensive guard in build_geo_tags to protect callers that bypass to_geotiff.
  • Add regression tests covering bool rejection and numeric/None nodata behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
xrspatial/geotiff/_writers/eager.py Rejects bool/np.bool_ nodata at the public writer entry point with a clear TypeError.
xrspatial/geotiff/_geotags.py Adds a belt-and-braces rejection of bool/np.bool_ before emitting TAG_GDAL_NODATA.
xrspatial/geotiff/tests/test_nodata_bool_rejection_1911.py New regression coverage for bool rejection and numeric/None nodata behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

[True, False, np.bool_(True), np.bool_(False)],
)
def test_build_geo_tags_rejects_bool_nodata(bad):
"""The lower-level builder also rejects bool, in case ``to_geotiff`` is bypassed."""
@brendancol brendancol merged commit f70b853 into main May 15, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance PR touches performance-sensitive code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants