Skip to content

Improve error messages in uxarray/core - #1678

Open
Sevans711 wants to merge 4 commits into
mainfrom
sevans/error-messages-core
Open

Improve error messages in uxarray/core#1678
Sevans711 wants to merge 4 commits into
mainfrom
sevans/error-messages-core

Conversation

@Sevans711

@Sevans711Sevans711 commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Closes#1677 (sub-issue of #1617)

Overview

Makes error messages clearer and more informative throughout uxarray/core. As suggested by #1617 this is attempting to be an exhaustive fix for all desired error message improvements in uxarray/core, while touching nothing outside of uxarray/core.

Tiny expansion of scope: fixes confusing/misleading error types in a few places missed by #1622:

  1. ValueError → TypeError in open_dataset() error related to either passing the wrong number of input args or using the wrong types of objects for inputs. TypeError is more appropriate than ValueError in both of those cases.
  2. ValueError → TypeError in UxDataArray.zonal_mean() errors raised when not isinstance(lat, (tuple, float, int, list, np.ndarray)) or when not isinstance(lat, (tuple, list, np.ndarray)).
  3. ValueError → TypeError in UxDataArray.from_healpix() error raised when not isinstance(da, xr.DataArray).

Aside from this tiny expansion of scope there should be no functionality changes; the only differences in this PR are the changes to error message contents.

Additional notes:

  • Test suite updates to error message string matching is a good spot-check that these changes are working; the tests failed until I updated the test suite to match the new strings.
  • Intentionally did not touch error messages in concat() because fixing bugs there might lead to needing different kinds of messages anyway (see uxarray.concat implementation incomplete/buggy and needs a docstring #1642).
  • Ran benchmarks to make sure there isn't any performance hit. (Highly unlikely, but could happen if errors are used as part of control flow in a hot loop and any objects now placed into error message strings take non-negligible time to convert to string.) (Removed run-benchmarks label after seeing there is no performance hit.)

PR Checklist

General

  • An issue is created and linked
  • Added appropriate labels (if your uxarray repo permissions allow it)
  • Filled out Overview and Expected Usage (if applicable) sections

Testing & Benchmarking

  • [N/A] Adequate tests are created if there is new functionality
  • Tests are not too basic (such as simply calling a function and nothing else)
  • [N/A] Tests cover all major paths in your new functions
  • If this PR could affect performance, ran ASV benchmarks and confirmed they show expected behavior (add a new benchmark if necessary)

AI Disclosure

AI Usage: GitHub Copilot's inline code suggestions, some tiny chats with Claude about error message style.

  • I take responsibility for all AI-generated content in my PR.
  • I have tested all AI-generated content in my PR.

@Sevans711Sevans711 added documentation Improvements or additions to documentation improvement Improvements on existing features or infrastructure run-benchmark Run ASV benchmark workflow developer experience Makes the codebase easier to read, debug, maintain, or extend. design Design of an API, feature, or user interface (not just implementation details) labels Aug 17, 2026
@github-actions

github-actionsBot commented Aug 17, 2026

Copy link
Copy Markdown

ASV Benchmarking

Benchmark Comparison Results

Benchmarks that have stayed the same:

ChangeBefore [efc469d]After [7a15584]RatioBenchmark (Parameter)
201±1ms202±0.9ms1.00bench_connectivity.Connectivity.time_edge_face('120km')
12.4±0.2ms12.4±0.1ms1.00bench_connectivity.Connectivity.time_edge_face('480km')
201±0.7ms201±1ms1.00bench_connectivity.Connectivity.time_edge_node('120km')
11.1±0.1ms11.2±0.05ms1.00bench_connectivity.Connectivity.time_edge_node('480km')
203±1ms200±0.4ms0.98bench_connectivity.Connectivity.time_face_edge('120km')
11.6±0.03ms11.7±0.1ms1.01bench_connectivity.Connectivity.time_face_edge('480km')
900±5ms889±5ms0.99bench_connectivity.Connectivity.time_face_face('120km')
57.9±0.9ms57.0±0.7ms0.98bench_connectivity.Connectivity.time_face_face('480km')
71.8±2μs70.2±1μs0.98bench_connectivity.Connectivity.time_face_node('120km')
68.7±1μs67.1±2μs0.98bench_connectivity.Connectivity.time_face_node('480km')
414±10μs411±10μs0.99bench_connectivity.Connectivity.time_n_nodes_per_face('120km')
353±10μs364±10μs1.03bench_connectivity.Connectivity.time_n_nodes_per_face('480km')
204±3ms200±2ms0.98bench_connectivity.Connectivity.time_node_edge('120km')
11.6±0.1ms11.6±0.1ms1.00bench_connectivity.Connectivity.time_node_edge('480km')
86.4±1ms88.9±4ms1.03bench_connectivity.Connectivity.time_node_face('120km')
5.35±0.05ms5.29±0.03ms0.99bench_connectivity.Connectivity.time_node_face('480km')
8.86±0.1ms8.87±0.09ms1.00face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
2.84±0.05ms2.79±0.05ms0.98face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
10.5±10s10.4±10ms~0.00face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
2.27±0.02ms2.22±0.06ms0.98face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
57.3k57.3k1.00face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
12.3k12.3k1.00face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
123k123k1.00face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
1281281.00face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
1.27M1.27M1.00face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
50.1k50.1k1.00face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
1.48M1.48M1.00face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
7127121.00face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
1.98M1.98M1.00face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
1.99M1.99M1.00face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
2.15M2.15M1.00face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
38.3k38.3k1.00face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
336M336M1.00face_bounds.FaceBoundsColdStartRss.peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
365M367M1.01face_bounds.FaceBoundsColdStartRss.peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
337M338M1.00face_bounds.FaceBoundsColdStartRss.peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
336M337M1.00face_bounds.FaceBoundsColdStartRss.peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
1.25±0.03μs1.22±0.04μs0.98geometry_kernels.AccucrossKernels.time_accucross
2.76±0.02μs2.82±0.04μs1.02geometry_kernels.AccucrossKernels.time_accucross_pair
466±20ns446±20ns0.96geometry_kernels.EFTPrimitives.time_acc_sqrt_re
461±20ns426±5ns0.92geometry_kernels.EFTPrimitives.time_diff_of_products
406±20ns401±20ns0.99geometry_kernels.EFTPrimitives.time_two_prod
385±10ns401±9ns1.04geometry_kernels.EFTPrimitives.time_two_sum
1.61±0.08μs1.54±0.05μs0.96geometry_kernels.GCAConstLatIntersection.time_accux_constlat_kernel
1.16±0.03μs1.15±0.03μs0.99geometry_kernels.GCAConstLatIntersection.time_gca_const_lat_intersection
1.94±0.05μs1.96±0.03μs1.01geometry_kernels.GCAConstLatIntersection.time_try_gca_const_lat_intersection
1.71±0.03μs1.72±0.04μs1.01geometry_kernels.GCAGCAIntersection.time_accux_gca_kernel
1.37±0.03μs1.40±0.02μs1.03geometry_kernels.GCAGCAIntersection.time_gca_gca_intersection
2.18±0.04μs2.21±0.04μs1.02geometry_kernels.GCAGCAIntersection.time_try_gca_gca_intersection
55.9±3μs53.2±0.6μs0.95geometry_kernels.OrientPredicates.time_on_minor_arc
1.16±0.06μs1.13±0.02μs0.97geometry_kernels.OrientPredicates.time_orient3d_on_sphere
2.72±0.1ms2.61±0.01ms0.96geometry_samebody.SameBodyConstLat.time_accux_dispatch
1.17±0ms1.17±0ms1.00geometry_samebody.SameBodyConstLat.time_accux_kernel
1.72±0.01ms1.72±0.01ms1.00geometry_samebody.SameBodyConstLat.time_fp64_dispatch
150±4μs147±0.8μs0.98geometry_samebody.SameBodyConstLat.time_fp64_kernel
32.5±0.08ms32.2±0.03ms0.99geometry_samebody_gcagca.SameBodyGcaGca.time_accux_dispatch
10.2±0.01ms10.3±0ms1.00geometry_samebody_gcagca.SameBodyGcaGca.time_accux_kernel
26.5±0.02ms26.5±0.02ms1.00geometry_samebody_gcagca.SameBodyGcaGca.time_fp64_dispatch
4.85±0.01ms5.07±0.03ms1.05geometry_samebody_gcagca.SameBodyGcaGca.time_fp64_kernel
837±7ms826±10ms0.99import.Imports.timeraw_import_uxarray
293M293M1.00import.Imports.track_peakmem_import_uxarray
2.79±0.02ms2.88±0.03ms1.03mpas_ocean.CheckNorm.time_check_norm('120km')
2.25±0.02ms2.30±0.03ms1.02mpas_ocean.CheckNorm.time_check_norm('480km')
853±10ms852±8ms1.00mpas_ocean.ConnectivityConstruction.time_face_face_connectivity('120km')
54.9±0.6ms55.1±0.6ms1.00mpas_ocean.ConnectivityConstruction.time_face_face_connectivity('480km')
690±20μs693±10μs1.00mpas_ocean.ConnectivityConstruction.time_n_nodes_per_face('120km')
609±10μs606±20μs0.99mpas_ocean.ConnectivityConstruction.time_n_nodes_per_face('480km')
5.46±0.01ms5.46±0.06ms1.00mpas_ocean.ConstructFaceLatLon.time_cartesian_averaging('120km')
4.01±0.02ms4.02±0.04ms1.00mpas_ocean.ConstructFaceLatLon.time_cartesian_averaging('480km')
3.43±0s3.47±0.04s1.01mpas_ocean.ConstructFaceLatLon.time_welzl('120km')
224±0.8ms221±0.9ms0.99mpas_ocean.ConstructFaceLatLon.time_welzl('480km')
18.2±0.05ms18.2±0.02ms1.00mpas_ocean.ConstructTreeStructures.time_ball_tree('120km')
1.05±0.02ms1.06±0.01ms1.01mpas_ocean.ConstructTreeStructures.time_ball_tree('480km')
10.6±0.03ms10.6±0.04ms1.00mpas_ocean.ConstructTreeStructures.time_kd_tree('120km')
747±10μs743±5μs0.99mpas_ocean.ConstructTreeStructures.time_kd_tree('480km')
721±6ms724±2ms1.00mpas_ocean.CrossSections.time_const_lat('120km', 1)
365±8ms365±1ms1.00mpas_ocean.CrossSections.time_const_lat('120km', 2)
188±2ms188±1ms1.00mpas_ocean.CrossSections.time_const_lat('120km', 4)
552±4ms559±2ms1.01mpas_ocean.CrossSections.time_const_lat('480km', 1)
281±1ms282±1ms1.00mpas_ocean.CrossSections.time_const_lat('480km', 2)
146±2ms145±1ms1.00mpas_ocean.CrossSections.time_const_lat('480km', 4)
26.3±0.2ms25.1±0.09ms0.96mpas_ocean.DualMesh.time_dual_mesh_construction('120km')
3.56±0.1ms3.61±0.08ms1.02mpas_ocean.DualMesh.time_dual_mesh_construction('480km')
62.9±0.6ms62.1±8ms0.99mpas_ocean.FaceAreas.time_face_areas('120km')
4.88±5s8.23±5ms~0.00mpas_ocean.FaceAreas.time_face_areas('480km')
229k229k1.00mpas_ocean.FaceAreas.track_nbytes_face_areas('120km')
14.3k14.3k1.00mpas_ocean.FaceAreas.track_nbytes_face_areas('480km')
2.12M2.12M1.00mpas_ocean.FaceAreas.track_peakmem_face_areas('120km')
823k823k1.00mpas_ocean.FaceAreas.track_peakmem_face_areas('480km')
961±3ms942±9ms0.98mpas_ocean.GeoDataFrame.time_to_geodataframe('120km', False)
53.0±0.3ms54.8±2ms1.03mpas_ocean.GeoDataFrame.time_to_geodataframe('120km', True)
86.1±1ms84.9±0.4ms0.99mpas_ocean.GeoDataFrame.time_to_geodataframe('480km', False)
5.96±0.2ms5.73±0.06ms0.96mpas_ocean.GeoDataFrame.time_to_geodataframe('480km', True)
177±7ms176±0.8ms0.99mpas_ocean.Gradient.time_gradient('120km')
12.5±0.05ms12.3±0.2ms0.99mpas_ocean.Gradient.time_gradient('480km')
457k457k1.00mpas_ocean.Gradient.track_nbytes_gradient('120km')
28.7k28.7k1.00mpas_ocean.Gradient.track_nbytes_gradient('480km')
5.08M5.08M1.00mpas_ocean.Gradient.track_peakmem_gradient('120km')
328k328k1.00mpas_ocean.Gradient.track_peakmem_gradient('480km')
351M352M1.00mpas_ocean.GradientColdStartRss.peakmem_gradient('120km')
331M331M1.00mpas_ocean.GradientColdStartRss.peakmem_gradient('480km')
387±6μs381±9μs0.98mpas_ocean.HoleEdgeIndices.time_construct_hole_edge_indices('120km')
218±10μs208±7μs0.96mpas_ocean.HoleEdgeIndices.time_construct_hole_edge_indices('480km')
566±10μs561±20μs0.99mpas_ocean.Integrate.time_integrate('120km')
513±20μs500±20μs0.98mpas_ocean.Integrate.time_integrate('480km')
18.4M18.4M1.00mpas_ocean.Integrate.track_nbytes_integrate('120km')
1.2M1.2M1.00mpas_ocean.Integrate.track_nbytes_integrate('480km')
181±0.8ms185±1ms1.02mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'exclude')
182±0.4ms183±2ms1.00mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'include')
182±1ms183±1ms1.01mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'split')
13.8±0.4ms13.8±0.07ms1.00mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'exclude')
13.8±0.2ms13.8±0.1ms1.01mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'include')
13.7±0.08ms13.8±0.1ms1.00mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'split')
435±20μs419±20μs0.96mpas_ocean.PointInPolygon.time_face_search_lonlat('120km')
418±10μs397±10μs0.95mpas_ocean.PointInPolygon.time_face_search_lonlat('480km')
373±10μs391±9μs1.05mpas_ocean.PointInPolygon.time_face_search_xyz('120km')
370±10μs400±5μs1.08mpas_ocean.PointInPolygon.time_face_search_xyz('480km')
242±1ms241±0.6ms0.99mpas_ocean.RemapDownsample.time_bilinear_remapping
294±7ms294±3ms1.00mpas_ocean.RemapDownsample.time_inverse_distance_weighted_remapping
15.9±0.08ms15.7±0.1ms0.99mpas_ocean.RemapDownsample.time_nearest_neighbor_remapping
1.42±0s1.43±0.01s1.01mpas_ocean.RemapUpsample.time_bilinear_remapping
37.4±0.3ms37.3±0.1ms1.00mpas_ocean.RemapUpsample.time_inverse_distance_weighted_remapping
12.7±0.05ms12.7±0.1ms1.00mpas_ocean.RemapUpsample.time_nearest_neighbor_remapping
25.7±0.6ms25.4±0.2ms0.99mpas_ocean.ZonalAverage.time_zonal_average('120km')
5.81±0.02ms5.88±0.03ms1.01mpas_ocean.ZonalAverage.time_zonal_average('480km')
6.79±0.07ms6.84±0.05ms1.01quad_hexagon.QuadHexagon.time_open_dataset
5.82±0.01ms5.82±0.06ms1.00quad_hexagon.QuadHexagon.time_open_grid
4084081.00quad_hexagon.QuadHexagon.track_nbytes_open_dataset
3923921.00quad_hexagon.QuadHexagon.track_nbytes_open_grid
73.8k73.8k1.00quad_hexagon.QuadHexagon.track_peakmem_open_dataset
73k72.7k1.00quad_hexagon.QuadHexagon.track_peakmem_open_grid

@Sevans711Sevans711 removed the run-benchmark Run ASV benchmark workflow label Aug 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

designDesign of an API, feature, or user interface (not just implementation details)developer experienceMakes the codebase easier to read, debug, maintain, or extend.documentationImprovements or additions to documentationimprovementImprovements on existing features or infrastructure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error messages improvements in uxarray/core

1 participant

@Sevans711