Skip to content

geotiff: CRS resolution should fail closed on unparseable strings by default #1929

@brendancol

Description

@brendancol

Describe the bug
The default CRS resolution path silently writes malformed input into the user-defined citation field.

_wkt_to_epsg returns None and emits a GeoTIFFFallbackWarning when pyproj is missing or the input cannot be parsed. The writer then stores the original string as wkt_fallback at _writers/eager.py:481 and :499. The geokey emitter at _geotags.py:1100 warns that many readers will lose the CRS, but it still writes the verbatim bytes into GTCitationGeoKey.

A caller who passes to_geotiff(..., crs="EPSG:4326") on a host without pyproj ends up with the literal string "EPSG:4326" in the citation field. That is not a WKT, and most non-GDAL readers drop the projection entirely. A caller who passes a malformed PROJ string lands the same garbage in the file.

For a foundational I/O module this is too permissive. Round-trip safety is part of the contract.

Expected behavior
By default, when pyproj is available and parsing fails, raise instead of warning. When pyproj is missing and the supplied string is not a recognised WKT (no PROJCS / GEOGCS / PROJCRS / GEOGCRS / COMPD_CS / COMPOUNDCRS root), refuse to write a citation-only file. Callers who explicitly want the citation-only output opt in.

Proposed fix

  1. Add an allow_unparseable_crs kwarg to to_geotiff / write_geotiff_gpu / write_vrt. Default False.
  2. When False and the resolution path lands wkt_fallback, raise ValueError with a message naming the offending string and pointing at the opt-in.
  3. When True, keep the existing warning + citation write.
  4. Keep the existing XRSPATIAL_GEOTIFF_STRICT=1 env path consistent so strict mode also exercises the new default.

Additional context
Surfaced by an external review of the geotiff module. The existing XRSPATIAL_GEOTIFF_STRICT env var already supports re-raising the pyproj exception. This issue is about flipping the default and adding a per-call opt-in.

Metadata

Metadata

Assignees

No one assigned

    Labels

    apiAPI design and consistencybugSomething isn't workinginput-validationInput validation and error messages

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions