Version
v2026.07.0
How did you install UXarray?
Source
What happened?
Writing a ragged grid (mixed face sizes) to ESMF silently corrupts padded slots instead of preserving them as fill values: _encode_esmf in uxarray/io/_esmf.py adds 1 to every entry of face_node_connectivity, including INT_FILL_VALUE padding, before encoding as int32. INT_FILL_VALUE + 1 (-2**63 + 1) truncates under that narrowing cast to 1, so padding is written as a valid node index (node 0) instead of the declared _FillValue of -1, and the numElementConn fallback (which counts entries != -1) inherits the same error and reports every face at maximum width; a triangle padded to width 4 round-trips back as a quad with an extra vertex at node 0. The reader (_read_esmf) has the mirror-image bug: CF decoding turns the on-disk -1 into NaN, and the code casts to INT_DTYPE before checking for the fill, which only happens to produce INT_FILL_VALUE on platforms where NaN casts to INT64_MIN (x86) — on arm64 it casts to 0, decoding padding to -1, a valid negative index that silently wraps to the last node rather than raising the IndexError INT_FILL_VALUE is designed to trigger. Both directions fail without any exception or warning; only ragged grids are affected, which is why test_esmf_round_trip_consistency (using the all-quad outCSne30 fixture) never caught it.
What did you expect to happen?
The fill value should not be able to be cast as a valid value or overflow into a valid value (positive or negative, since Python is like that).
Can you provide a MCVE to repoduce the bug?
import numpy as np, xarray as xr, uxarray as ux
from uxarray.constants import INT_FILL_VALUE as fv
# one quad, one triangle padded to width 4
fnc = np.array([[0, 1, 2, 3], [1, 4, 2, fv]])
grid = ux.Grid.from_topology(
np.array([0., 10, 10, 0, 20]), np.array([0., 0, 10, 10, 0]), fnc, fill_value=fv
)
grid.to_xarray(grid_format="ESMF").to_netcdf("out.nc")
raw = xr.open_dataset("out.nc", mask_and_scale=False)
print(raw["elementConn"].values) # [[1 2 3 4] [2 5 3 1]] <- expected -1 in last slot
print(raw["numElementConn"].values) # [4 4] <- expected [4 3]
print(ux.open_grid("out.nc").face_node_connectivity.values)
Version
v2026.07.0
How did you install UXarray?
Source
What happened?
Writing a ragged grid (mixed face sizes) to ESMF silently corrupts padded slots instead of preserving them as fill values: _encode_esmf in uxarray/io/_esmf.py adds 1 to every entry of face_node_connectivity, including INT_FILL_VALUE padding, before encoding as int32. INT_FILL_VALUE + 1 (-2**63 + 1) truncates under that narrowing cast to 1, so padding is written as a valid node index (node 0) instead of the declared _FillValue of -1, and the numElementConn fallback (which counts entries != -1) inherits the same error and reports every face at maximum width; a triangle padded to width 4 round-trips back as a quad with an extra vertex at node 0. The reader (_read_esmf) has the mirror-image bug: CF decoding turns the on-disk -1 into NaN, and the code casts to INT_DTYPE before checking for the fill, which only happens to produce INT_FILL_VALUE on platforms where NaN casts to INT64_MIN (x86) — on arm64 it casts to 0, decoding padding to -1, a valid negative index that silently wraps to the last node rather than raising the IndexError INT_FILL_VALUE is designed to trigger. Both directions fail without any exception or warning; only ragged grids are affected, which is why test_esmf_round_trip_consistency (using the all-quad outCSne30 fixture) never caught it.
What did you expect to happen?
The fill value should not be able to be cast as a valid value or overflow into a valid value (positive or negative, since Python is like that).
Can you provide a MCVE to repoduce the bug?