Skip to content

Add custom error types in uxarray#1621

Open
Sevans711 wants to merge 4 commits into
mainfrom
custom-errors
Open

Add custom error types in uxarray#1621
Sevans711 wants to merge 4 commits into
mainfrom
custom-errors

Conversation

@Sevans711

@Sevans711 Sevans711 commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Closes #1556

Overview

Adds custom error types in uxarray. Defining custom error types can help with:

  • Quickly presenting relevant info (e.g. "DataCenteringError" name quickly clarifies this is about data being centered incorrectly, e.g. centered on nodes but expected it to be on faces). This could speed up debugging for developers and users alike.
  • Cleaner error handling within/outside of uxarray (e.g., catch "uxarray.errors.DimensionError" without catching other ValueErrors by accident).

In particular, this PR adds the following error types:

class DataCenteringError(ValueError):
    """data centering issue, such as expecting node-centered data but got edge-centered."""


class DimensionError(ValueError):
    """issue with dimension(s), such as wrong size(s), name(s), or number of dimensions."""


class GridInvalidError(ValueError):
    """data does not correspond to a valid uxarray.Grid.
    E.g., unrecognized format, duplicate nodes, or some faces with area < 0.
    """


class GridsMismatchError(ValueError):
    """attempted to perform an operation involving two incompatible uxarray.Grid objects"""

Small expansion of scope

This PR expands scope slightly beyond that of the original issue as follows:

  • move YacNotAvailableError from uxarray/remap/yac.py to uxarray/errors.py.

The following justification for this move is provided in the docstring at the top of errors.py:

Defining all such custom error types in this file, instead of throughout the codebase, helps with maintainability, discoverability, and convenience, as the import syntax will always be "import uxarray.errors.CustomError", and help(uxarray.errors) will list all custom error types in one place.

Though, this could be reverted if PR reviewers disagree or feel that this should be scoped as a separate issue instead.

Compatibility notes:

This PR should be fully backwards compatible, or nearly fully backwards compatible. Compatibility is maintained via subclassing. For example, any code catching ValueError will still catch any of the newly-defined custom error types, because they inherit from ValueError.

This PR adjusts two tests to check that custom error types are indeed being raised (e.g. with pytest.raises(DataCenteringError) instead of with pytest.raises(ValueError)). It does not adjust all tests to the new error types because it is desirable to see that the existing tests still pass, to confirm there are no breaking changes here.

Thinking about it a bit further, there are three technically-possible breakage points for existing code, but only for hopefully-very-unlikely code design patterns:

  1. Any string-based error processing which checks for string match to error class name, e.g. repr(err).startswith("ValueError")
  2. Any processing which checks for type equality, e.g. type(err) == ValueError
  3. Any processing which specifically excludes subclasses, e.g. isinstance(err, Exception) and not isinstance(err, ValueError), could fail in some cases. This PR replaces Exception with a custom error type in some cases, such as using DataCenteringError instead of Exception in a few places in grid.py.

Other Recommended Changes (Not Implemented Here)

Should custom errors become part of the public API? I would be interested in at least adding import uxarray.errors in uxarray.__init__.py, so that users who have imported uxarray already can do things like: ux.errors.DimensionError without needing to remember to add another import statement like from uxarray.errors import DimensionError.

There are a few locations where the new error types would better describe the actual error, but which are not included in this PR because they could break backwards compatibility. These could be added here if PR reviewers want, or split into a separate issue and PR afterwards. Including these here is not necessary to close issue #1556.

  • RuntimeError → GridInvalidError, in UxDataArray.get_dual, UxDataset.get_dual, and Grid.get_dual: "Duplicate nodes found, cannot construct dual"
  • RuntimeError → DimensionError, in Grid.from_face_vertices: f"Invalid Input Dimension: {face_vertices.ndim}. Expected dimension should be 3: [n_face, n_node, two/three] or 2 when only one face is passed in."
  • RuntimeError → GridInvalidError, in Grid.validate: "Mesh validation failed."
  • AssertionError → DimensionError, in grid.neighbors._prepare_xy_for_query: "The dimension of each coordinate pair must be two (lon, lat). Did you attempt to query using Cartesian (x, y, z) coordinates?", and "The dimension of each coordinate pair must be two (lon, lat).)"
  • AssertionError → DimensionError, in grid.neighbors._prepare_xyz_for_query: (similar messages as above)
  • RuntimeError → GridInvalidError, in io.utils._parse_grid_type: "Failed to parse uxgrid information from xarray.Dataset."

I also put together a variety of error-type changes I would recommend but which are unrelated to this PR, because they do not use the new error types. (Example: ValueError → TypeError in grid.utils.make_setter: f"{key} must be an xr.DataArray", which gets raised if not isinstance(value, xr.DataArray).) I have opened a separate issue to track those, see #1622.

PR Checklist

General

  • An issue is linked created and linked
  • Add appropriate labels
  • Filled out Overview and Expected Usage (if applicable) sections

Testing

  • Adequate tests are created if there is new functionality
  • Tests cover all possible logical paths in your function
  • Tests are not too basic (such as simply calling a function and nothing else)

Documentation

  • Docstrings have been added to all new functions
  • Docstrings have updated with any function changes
  • [N/A] Internal functions have a preceding underscore (_) and have been added to docs/internal_api/index.rst
  • [N/A] User functions have been added to docs/user_api/index.rst

Adds DataCenteringError, DimensionError, GridInvalidError, and GridsMismatchError. Replaces existing errors with one of these where appropriate AND where it will not break backwards compatibility.

Kept notes (will include in PR writeup) about places where it would break compatibility, and did not change those places yet.
spot check that custom error types are working: changes two existing tests to catch custom error types.

Does not change many other tests, because it is also desirable to confirm that these changes are actually backwards-compatible, by not messing with the test suite too much.
@Sevans711 Sevans711 added new feature New feature or request developer experience Makes the codebase easier to read, debug, maintain, or extend. labels Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

developer experience Makes the codebase easier to read, debug, maintain, or extend. new feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

custom error types in uxarray

1 participant