elastic/elasticsearch · error · IllegalArgumentException
Invalid base cell looking for neighbor
Error message
Invalid base cell looking for neighbor
What it means
Thrown by HexRing.h3NeighborInDirection when the base-cell field of the origin index is outside [0, NUM_BASE_CELLS). h3NeighborInDirection uses the base cell to index baseCellNeighbors/baseCellNeighbor60CCWRots, so an out-of-range base cell would cause an ArrayIndexOutOfBoundsException; this guard throws a clear error instead. The method is package-private and reached via hexRingPosToH3, child/noChild pos methods, and areNeighbours' fallback.
Source
Thrown at libs/h3/src/main/java/org/elasticsearch/h3/HexRing.java:680
/**
* Returns the hexagon index neighboring the origin, in the direction dir.
*
* Implementation note: The only reachable case where this returns -1 is if the
* origin is a pentagon and the translation is in the k direction. Thus,
* -1 can only be returned if origin is a pentagon.
*
* @param origin Origin index
* @param dir Direction to move in
* @return H3Index of the specified neighbor or -1 if there is no more neighbor
*/
static long h3NeighborInDirection(long origin, int dir) {
long current = origin;
int newRotations = 0;
int oldBaseCell = H3Index.H3_get_base_cell(current);
if (oldBaseCell < 0 || oldBaseCell >= Constants.NUM_BASE_CELLS) { // LCOV_EXCL_BR_LINE
// Base cells less than zero can not be represented in an index
throw new IllegalArgumentException("Invalid base cell looking for neighbor");
}
int oldLeadingDigit = H3Index.h3LeadingNonZeroDigit(current);
// Adjust the indexing digits and, if needed, the base cell.
int r = H3Index.H3_get_resolution(current) - 1;
while (true) {
if (r == -1) {
current = H3Index.H3_set_base_cell(current, baseCellNeighbors[oldBaseCell][dir]);
newRotations = baseCellNeighbor60CCWRots[oldBaseCell][dir];
if (H3Index.H3_get_base_cell(current) == INVALID_BASE_CELL) {
// Adjust for the deleted k vertex at the base cell level.
// This edge actually borders a different neighbor.
current = H3Index.H3_set_base_cell(current, baseCellNeighbors[oldBaseCell][CoordIJK.Direction.IK_AXES_DIGIT.digit()]);
newRotations = baseCellNeighbor60CCWRots[oldBaseCell][CoordIJK.Direction.IK_AXES_DIGIT.digit()];
// perform the adjustment for the k-subsequence we're skipping
// over.View on GitHub (pinned to db6a809a66)
Solutions
- Validate with H3.h3IsValid(h3) before any neighbor/ring/child operation.
- Re-derive indexes from lat/lng via geoToH3 rather than trusting external longs.
- If you must accept raw longs, treat h3IsValid == false as a hard error at the trust boundary.
Example fix
// before
long[] ring = H3.hexRing(rawLong); // throws Invalid base cell if base-cell field invalid
// after
if (H3.h3IsValid(rawLong) == false) {
throw new IllegalArgumentException("not a valid H3 index: " + rawLong);
}
long[] ring = H3.hexRing(rawLong); Defensive patterns
Strategy: validation
Validate before calling
static long[] safeRing(long h3) {
if (!org.elasticsearch.h3.H3.h3IsValid(h3)) {
throw new IllegalArgumentException("not a valid H3 index: " + h3);
}
return org.elasticsearch.h3.H3.hexRing(h3);
} Type guard
static boolean isUsable(long h3) {
return org.elasticsearch.h3.H3.h3IsValid(h3);
} Try / catch
try {
return H3.hexRing(h3);
} catch (IllegalArgumentException e) {
if (e.getMessage().equals("Invalid base cell looking for neighbor")) {
throw new IllegalArgumentException("corrupt or non-H3 index: " + h3, e);
}
throw e;
} Prevention
- Validate every external long with h3IsValid before any neighbor/ring/child op.
- Re-derive indexes from lat/lng via geoToH3.
- Reject corrupt longs at the trust boundary rather than deep in a neighbor walk.
When it happens
Trigger: An operation that walks neighbors (hexRing, hexRingPosToH3, noChildIntersectingPosToH3, areNeighbours fallback) is given an origin long whose base-cell nibble is invalid. With public API input this is masked by earlier validity checks; it surfaces when a corrupt or non-H3 long is passed in.
Common situations: Passing an opaque long from an external/untrusted source into a neighbor walk without validation; deserialization/endian corruption of an H3 long; mixing indexes from incompatible H3 versions whose base-cell layout differs.
Related errors
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/208fdccfcb657e15.
Report an issue: GitHub.