Skip to content

Commit 0a4b378

Browse files
shoyerdcherian
andauthored
Use add_note() to annotate exceptions when encoding fails (#10464)
Co-authored-by: Deepak Cherian <dcherian@users.noreply.github.com>
1 parent 8d2e563 commit 0a4b378

File tree

4 files changed

+44
-7
lines changed

4 files changed

+44
-7
lines changed

doc/whats-new.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ New Features
1414
~~~~~~~~~~~~
1515
- Expose :py:class:`~xarray.indexes.RangeIndex`, and :py:class:`~xarray.indexes.CoordinateTransformIndex` as public api
1616
under the ``xarray.indexes`` namespace. By `Deepak Cherian <https://github.com/dcherian>`_.
17+
- Better error messages when encoding data to be written to disk fails (:pull:`10464`).
18+
By `Stephan Hoyer <https://github.com/shoyer>`_
1719

1820
Breaking changes
1921
~~~~~~~~~~~~~~~~

xarray/backends/common.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -389,9 +389,23 @@ def encode(self, variables, attributes):
389389
attributes : dict-like
390390
391391
"""
392-
variables = {k: self.encode_variable(v, name=k) for k, v in variables.items()}
393-
attributes = {k: self.encode_attribute(v) for k, v in attributes.items()}
394-
return variables, attributes
392+
encoded_variables = {}
393+
for k, v in variables.items():
394+
try:
395+
encoded_variables[k] = self.encode_variable(v)
396+
except Exception as e:
397+
e.add_note(f"Raised while encoding variable {k!r} with value {v!r}")
398+
raise
399+
400+
encoded_attributes = {}
401+
for k, v in attributes.items():
402+
try:
403+
encoded_attributes[k] = self.encode_attribute(v)
404+
except Exception as e:
405+
e.add_note(f"Raised while encoding attribute {k!r} with value {v!r}")
406+
raise
407+
408+
return encoded_variables, encoded_attributes
395409

396410
def encode_variable(self, v, name=None):
397411
"""encode one variable"""
@@ -641,9 +655,7 @@ def encode(self, variables, attributes):
641655
variables = {
642656
k: ensure_dtype_not_object(v, name=k) for k, v in variables.items()
643657
}
644-
variables = {k: self.encode_variable(v, name=k) for k, v in variables.items()}
645-
attributes = {k: self.encode_attribute(v) for k, v in attributes.items()}
646-
return variables, attributes
658+
return super().encode(variables, attributes)
647659

648660

649661
class BackendEntrypoint:

xarray/conventions.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,13 @@ def cf_encoder(variables: T_Variables, attributes: T_Attrs):
792792
# add encoding for time bounds variables if present.
793793
_update_bounds_encoding(variables)
794794

795-
new_vars = {k: encode_cf_variable(v, name=k) for k, v in variables.items()}
795+
new_vars = {}
796+
for k, v in variables.items():
797+
try:
798+
new_vars[k] = encode_cf_variable(v, name=k)
799+
except Exception as e:
800+
e.add_note(f"Raised while encoding variable {k!r} with value {v!r}")
801+
raise
796802

797803
# Remove attrs from bounds variables (issue #2921)
798804
for var in new_vars.values():

xarray/tests/test_backends_common.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
from __future__ import annotations
22

3+
import re
4+
35
import numpy as np
46
import pytest
57

8+
import xarray as xr
69
from xarray.backends.common import _infer_dtype, robust_getitem
10+
from xarray.tests import requires_scipy
711

812

913
class DummyFailure(Exception):
@@ -43,3 +47,16 @@ def test_robust_getitem() -> None:
4347
def test_infer_dtype_error_on_mixed_types(data):
4448
with pytest.raises(ValueError, match="unable to infer dtype on variable"):
4549
_infer_dtype(data, "test")
50+
51+
52+
@requires_scipy
53+
def test_encoding_failure_note():
54+
# Create an arbitrary value that cannot be encoded in netCDF3
55+
ds = xr.Dataset({"invalid": np.array([2**63 - 1], dtype=np.int64)})
56+
with pytest.raises(
57+
ValueError,
58+
match=re.escape(
59+
"Raised while encoding variable 'invalid' with value <xarray.Variable"
60+
),
61+
):
62+
ds.to_netcdf()

0 commit comments

Comments
 (0)