2025, Nov 08 17:00

How to resolve pysheds 'nodata value not representable in dtype' TypeError on NumPy 2 (NEP 50)

Troubleshooting pysheds on NumPy 2: fix the 'nodata value not representable in dtype' TypeError during flow direction and accumulation by pinning NumPy 1.x.

Running pysheds against a modern stack and hitting TypeError: nodata value not representable in dtype of array? You are not alone. The failure typically appears when computing flow directions and is tied to NumPy 2 behavior changes, not to your raster or algorithm setup.

Repro case

The scenario below illustrates the issue end to end. The logic is straightforward: load a DEM, resolve flats, compute flow directions, then accumulation. The names are arbitrary; the flow stays the same.

import numpy as np
from pysheds.grid import Grid as PsGrid

# Load DEM from GeoTIFF
source_path = 'CLSA_LiDAR.tif'
mesh = PsGrid.from_raster(source_path)
heightmap = mesh.read_raster(source_path)

# Resolve flats and compute flow directions
heightmap_adj = mesh.resolve_flats(heightmap)
directions = mesh.flowdir(heightmap_adj)

# Flow accumulation
accum_map = mesh.accumulation(directions)

On NumPy 2, the failure typically reports a stack trace that includes a check like np.can_cast(viewfinder.nodata, obj.dtype, casting='safe') and then surfaces as the nodata TypeError.

What is actually going on

The error is a symptom of a compatibility gap between pysheds and NumPy 2. The stack trace contains a key hint:

This change was part of adopting NEP 50, we may explicitly allow them again in the future.

NumPy 2 adopts NEP 50, which changes how certain scalar promotions and casting semantics behave. In this code path, a safe casting check involving nodata triggers a TypeError under NumPy 2, which then results in the user-facing message that nodata cannot be represented in the array dtype.

Fix

The practical resolution is to run pysheds with a NumPy 1.x release. Using NumPy 1.22 resolves the issue in practice. Other NumPy 1.x builds, such as 1.26.x, can also work; if needed, choose a more conservative 1.x version until your environment is stable. After switching to NumPy 1.x, the same script runs without code changes.

import numpy as np
from pysheds.grid import Grid as PsGrid

# Load DEM
src = 'CLSA_LiDAR.tif'
grid_obj = PsGrid.from_raster(src)
dem_arr = grid_obj.read_raster(src)

# Flow prep and analysis
dem_adj = grid_obj.resolve_flats(dem_arr)
flow_dir = grid_obj.flowdir(dem_adj)
accumulated = grid_obj.accumulation(flow_dir)

Users have confirmed that downgrading NumPy removes the error, and the same incompatibility can surface in other parts of a project that rely on similar casting behavior.

Why this matters

Adopting a major dependency upgrade like NumPy 2 can introduce behavior changes in low-level operations that geospatial stacks depend on. When a library hasn’t fully adapted to the new semantics, seemingly unrelated steps—like nodata checks inside raster views—can break critical workflows such as flow direction and accumulation. Understanding that the failure is environmental, not algorithmic, helps you focus on the right fix quickly.

Takeaways

If you hit nodata value not representable in dtype of array while using pysheds, align the environment to a NumPy 1.x release. Versions like 1.22 are known to work, and 1.26.x can also be viable. Once NumPy is pinned to a compatible 1.x build, re-run the same code—the algorithm and API don’t require changes. For ongoing work, keep an eye on NumPy 2 adoption notes and the evolution of pysheds’ compatibility so you can upgrade when it’s safe without disrupting hydrologic processing pipelines.

The article is based on a question from StackOverflow by Kay Khaing Kyaw and an answer by wp78de.