elastic/elasticsearch · error · IllegalArgumentException
invalid child position
Error message
invalid child position
What it means
Thrown by H3.childPosToH3 when childPos is negative or exceeds the valid range for the cell's shape: 0..6 for hexagons (center + 6 edges) and 0..5 for pentagons (center + 5 edges, since the k-axis digit is skipped). The position must index into the cell's finite child set.
Source
Thrown at libs/h3/src/main/java/org/elasticsearch/h3/H3.java:273
return h3ToStringList(h3ToChildren(stringToH3(h3Address)));
}
/**
* Returns the child cell at the given position
*/
public static long childPosToH3(long h3, int childPos) {
final int childrenRes = H3Index.H3_get_resolution(h3) + 1;
if (childrenRes > MAX_H3_RES) {
throw new IllegalArgumentException("Resolution overflow");
}
final long childH = H3Index.H3_set_resolution(h3, childrenRes);
if (childPos == 0) {
return H3Index.H3_set_index_digit(childH, childrenRes, CoordIJK.Direction.CENTER_DIGIT.digit());
}
final boolean isPentagon = isPentagon(h3);
final int maxPos = isPentagon ? 5 : 6;
if (childPos < 0 || childPos > maxPos) {
throw new IllegalArgumentException("invalid child position");
}
if (isPentagon) {
// Pentagon skip digit (position) is the number 1, therefore we add one
// to the current position.
return H3Index.H3_set_index_digit(childH, childrenRes, childPos + 1);
} else {
return H3Index.H3_set_index_digit(childH, childrenRes, childPos);
}
}
/**
* Returns the child address at the given position
*/
public static String childPosToH3(String h3Address, int childPos) {
return h3ToString(childPosToH3(stringToH3(h3Address), childPos));
}
private static final int[] PEN_INTERSECTING_CHILDREN_DIRECTIONS = new int[] { 3, 1, 6, 4, 2 };View on GitHub (pinned to db6a809a66)
Solutions
- Bound the loop by H3.h3ToChildrenSize(cell) (returns 7 for hexagons, 6 for pentagons) rather than a hardcoded 7.
- If accepting arbitrary user positions, validate 0 <= pos < h3ToChildrenSize(cell) before calling.
- Remember pentagons have one fewer child position (the deleted k-axis); never assume uniform 7.
Example fix
// before
for (int i = 0; i <= 6; i++) { // wrong for pentagons
long child = H3.childPosToH3(cell, i);
}
// after
for (int i = 0; i < H3.h3ToChildrenSize(cell); i++) {
long child = H3.childPosToH3(cell, i);
} Defensive patterns
Strategy: validation
Validate before calling
static long safeChildPos(long h3, int pos) {
int max = org.elasticsearch.h3.H3.h3ToChildrenSize(h3); // 7 hex / 6 pentagon
if (pos < 0 || pos >= max) {
throw new IllegalArgumentException("pos " + pos + " out of [0," + max + ")");
}
return org.elasticsearch.h3.H3.childPosToH3(h3, pos);
} Type guard
static boolean validChildPos(long h3, int pos) {
return pos >= 0 && pos < org.elasticsearch.h3.H3.h3ToChildrenSize(h3);
} Try / catch
try {
return H3.childPosToH3(h3, pos);
} catch (IllegalArgumentException e) {
if (e.getMessage().equals("invalid child position")) {
throw new IndexOutOfBoundsException("childPos " + pos + " invalid for " + h3);
}
throw e;
} Prevention
- Bound iteration by h3ToChildrenSize, not a hardcoded 7.
- Remember pentagons have 6 child positions, hexagons 7.
- Validate external position inputs against the cell-specific max.
When it happens
Trigger: Calling childPosToH3(cell, n) with n out of the legal band for that cell. A pentagon parent restricts positions to 0..5, so passing 6 against a pentagon throws; a hexagon parent accepts up to 6.
Common situations: Assuming 7 children for every cell and passing position 6 against a pentagon; computing positions from a hexagon-sized loop applied to a pentagon; off-by-one indexing from a caller that uses 1-based positions.
Related errors
- invalid ring position
- Invalid child resolution [{}]
- Illegal base cell
- Input is a base cell
- Resolution overflow
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/04d590d199485582.
Report an issue: GitHub.