elastic/elasticsearch · error · IllegalArgumentException
Undefined error checking for neighbors
Error message
Undefined error checking for neighbors
What it means
Thrown by HexRing.areNeighbours during the optimized same-parent fast path when a resolution digit equals the K_AXES_DIGIT and the shared parent is a pentagon. The k-axis is the deleted direction on pentagons, so the lookup tables cannot decide adjacency; the method declines to give a possibly-wrong answer. Note a separate empty-message IllegalArgumentException at the same call site guards INVALID_DIGIT.
Source
Thrown at libs/h3/src/main/java/org/elasticsearch/h3/HexRing.java:638
if (originParent == destinationParent) {
int originResDigit = H3Index.H3_get_index_digit(origin, resolution);
int destinationResDigit = H3Index.H3_get_index_digit(destination, resolution);
if (originResDigit == CoordIJK.Direction.CENTER_DIGIT.digit()
|| destinationResDigit == CoordIJK.Direction.CENTER_DIGIT.digit()) {
return true;
}
if (originResDigit >= CoordIJK.Direction.INVALID_DIGIT.digit()) {
// Prevent indexing off the end of the array below
throw new IllegalArgumentException("");
}
if ((originResDigit == CoordIJK.Direction.K_AXES_DIGIT.digit()
|| destinationResDigit == CoordIJK.Direction.K_AXES_DIGIT.digit()) && H3.isPentagon(originParent)) {
// If these are invalid cells, fail rather than incorrectly
// reporting neighbors. For pentagon cells that are actually
// neighbors across the deleted subsequence, they will fail the
// optimized check below, but they will be accepted by the
// gridDisk check below that.
throw new IllegalArgumentException("Undefined error checking for neighbors");
}
// These sets are the relevant neighbors in the clockwise
// and counter-clockwise
if (NEIGHBORSETCLOCKWISE[originResDigit].digit() == destinationResDigit
|| NEIGHBORSETCOUNTERCLOCKWISE[originResDigit].digit() == destinationResDigit) {
return true;
}
}
}
// Otherwise, we have to determine the neighbor relationship the "hard" way.
for (int i = 0; i < 6; i++) {
long neighbor = h3NeighborInDirection(origin, DIRECTIONS[i].digit());
if (neighbor != -1) {
// -1 is an expected case when trying to traverse off of
// pentagons.
if (destination == neighbor) {
return true;
}View on GitHub (pinned to db6a809a66)
Solutions
- Wrap H3.areNeighborCells in a try/catch for IllegalArgumentException and, on this specific message, fall back to a geometry-based adjacency test (e.g. compare h3ToGeoBoundary / great-circle distance) or treat as not-neighbors per your domain.
- Prefer using H3's gridDisk/k-ring based neighborhood computation if available, which handles pentagon edges without this fast-path failure.
- Validate inputs with h3IsValid first to rule out corrupt indexes; if inputs are valid, this is a known pentagon-geometry limitation, not a caller bug.
Example fix
// before
boolean near = H3.areNeighborCells(a, b); // may throw on pentagon k-axis edge
// after
boolean near;
try {
near = H3.areNeighborCells(a, b);
} catch (IllegalArgumentException e) {
// fast path cannot decide pentagon k-axis adjacency
near = geometryAdjacent(a, b); // your fallback
} Defensive patterns
Strategy: try-catch
Validate before calling
// Cannot fully pre-validate this geometric edge case; input can be valid yet trigger it.
// Best prevention is wrapping the call and using a fallback adjacency test.\nstatic boolean robustNeighbors(long a, long b) {
if (!org.elasticsearch.h3.H3.h3IsValid(a) || !org.elasticsearch.h3.H3.h3IsValid(b)) return false;
try {
return org.elasticsearch.h3.H3.areNeighborCells(a, b);
} catch (IllegalArgumentException e) {
return false; // or a geometry-based fallback
}
} Try / catch
try {
return H3.areNeighborCells(a, b);
} catch (IllegalArgumentException e) {
if ("Undefined error checking for neighbors".equals(e.getMessage())) {
// pentagon k-axis edge the fast path cannot decide
return geometryAdjacent(a, b); // your fallback, or false
}
throw e;
} Prevention
- Treat areNeighborCells as fallible for pentagon-adjacency edge cases; wrap it.
- If you need robust adjacency, compute via boundary/distance rather than the fast path.
- Isolate the fallback so callers get a stable boolean contract.
When it happens
Trigger: Reached from H3.areNeighborCells when both cells share a pentagon parent at resolution > 1 and at least one has the k-axis (skipped) digit at that resolution. For genuinely adjacent cells across the deleted subsequence, the fallback gridDisk loop later would accept them, but the fast path throws first.
Common situations: This is largely an internal invariant condition triggered by specific pentagon-adjacency geometries; users feeding valid indexes can still hit it because the optimized path is taken before the robust fallback. It indicates an edge case the fast path does not handle.
Related errors
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/1e81d85c906a116b.
Report an issue: GitHub.