Skip to content

pathfinding: string barriers silently ignored, search_radius unvalidated, inconsistent start/goal and dims errors #3649

Description

@brendancol

Describe the bug

Error-handling audit of xrspatial/pathfinding.py, with the bad-input battery executed on numpy, dask+numpy, cupy, and dask+cupy. Four validation gaps in a_star_search / multi_stop_search.

1. String-typed barriers values are silently ignored (severity: critical)

Numba compares the float cell value against a unicode element, which is always False, so every barrier is dropped. No error, no warning, and the returned path crosses the cells the caller asked to block:

import numpy as np, xarray as xr
from xrspatial import a_star_search

data = np.ones((5, 9))
data[:, 4] = 0.0                      # wall of zeros
r = xr.DataArray(data, dims=('y', 'x'), attrs={'res': (1.0, 1.0)})
r['y'] = np.linspace(4, 0, 5); r['x'] = np.linspace(0, 8, 9)

a_star_search(r, (2.0, 0.0), (2.0, 8.0), barriers=[0])    # all-NaN: wall blocks the path (correct)
a_star_search(r, (2.0, 0.0), (2.0, 8.0), barriers=['0'])  # routes straight through the wall

Barrier values that arrive as strings (argparse, CSV, JSON config) give a wrong path that looks valid. A scalar (barriers=0 instead of [0]) dies instead with a numba TypingError: iteration over a 0-d array on the numpy/cupy backends and a bare TypeError on dask. Same on all four backends.

2. search_radius is never validated (severity: high)

  • a_star_search(agg, start, goal, search_radius=-1) returns all-NaN ("no path") on numpy and cupy even though a path exists. Through multi_stop_search the same input surfaces as the misleading ValueError: no path between waypoints 0 and 1.
  • Other geometries crash deep in the slicing code instead: ValueError: negative dimensions are not allowed (radius -3, interior points) or TypeError: slice indices must be integers or None or have an __index__ method (radius 2.5). Whether a float radius crashes or works depends on where start/goal sit relative to the grid edges.

3. multi_stop_search with mismatched dim names raises bare KeyError: 'y' (severity: medium)

a_star_search checks surface.dims != (y, x) and raises ValueError; multi_stop_search skips that check, so the same mistake dies inside xarray internals:

multi_stop_search(raster_with_lat_lon_dims, [start, goal])
# KeyError: 'y'   (from xarray's dataset_utils, no mention of the x=/y= parameters)

The a_star_search message has its own problems: `surface.coords` should be named as coordinates:(y, x) says "coords" where it means dims, is missing a space, and never shows the dims the raster actually has.

4. Scalar start/goal in a_star_search (severity: medium)

a_star_search(agg, 3.0, goal) raises TypeError: 'float' object is not subscriptable from inside _get_pixel_id. multi_stop_search already checks each waypoint has exactly 2 elements; a_star_search accepts anything, and a scalar waypoint in multi_stop_search itself hits TypeError: object of type 'float' has no len() at the check site.

Expected behavior

  • Non-numeric or non-1-D barriers raise a clear error naming the parameter and the offending dtype, before any kernel runs.
  • search_radius other than None or a non-negative integer is rejected up front.
  • multi_stop_search raises the same dims ValueError as a_star_search, and the message names the actual dims plus the x=/y= parameters.
  • start/goal get the same 2-element check that multi_stop_search applies to waypoints.

Found by the error-handling sweep on 2026-07-08. Exception types stay as they are for currently-raising paths; the two silent cases (1 and 2) start raising, which only affects calls that today return wrong output.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions