elastic/elasticsearch · error · IllegalArgumentException

resolution [{}] is out of range (must be 0 <= res <= 15)

Error message

resolution [{}]  is out of range (must be 0 <= res <= 15)

What it means

Thrown by H3's private checkResolution, invoked by geoToH3/geoToH3Address, northPolarH3, and southPolarH3 when res is not in [0, MAX_H3_RES] (0..15). The resolution selects which H3 grid level to use; values outside this band have no defined grid.

Source

Thrown at libs/h3/src/main/java/org/elasticsearch/h3/H3.java:607

                result *= base;
            }
            exp >>= 1;
            base *= base;
        }

        return result;
    }

    private static String[] h3ToStringList(long[] h3s) {
        return Arrays.stream(h3s).mapToObj(H3::h3ToString).toArray(String[]::new);
    }

    /**
     * @throws IllegalArgumentException <code>res</code> is not a valid H3 resolution.
     */
    private static void checkResolution(int res) {
        if (res < 0 || res > MAX_H3_RES) {
            throw new IllegalArgumentException("resolution [" + res + "]  is out of range (must be 0 <= res <= 15)");
        }
    }
}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Clamp/validate res to [0, H3.MAX_H3_RES] before calling any geoToH3/polar method.
  2. Use H3.MAX_H3_RES constant (15) rather than a magic number so version changes propagate.
  3. Return a clear upstream error for out-of-range user input instead of letting the library throw the generic message.

Example fix

// before
long cell = H3.geoToH3(lat, lng, userPrecision); // throws if userPrecision is 16 or -1

// after
int res = Math.max(0, Math.min(H3.MAX_H3_RES, userPrecision));
long cell = H3.geoToH3(lat, lng, res);
Defensive patterns

Strategy: validation

Validate before calling

static long safeGeoToH3(double lat, double lng, int res) {
    if (res < 0 || res > org.elasticsearch.h3.H3.MAX_H3_RES) {
        throw new IllegalArgumentException(
            "res " + res + " out of [0, " + org.elasticsearch.h3.H3.MAX_H3_RES + "]");
    }
    return org.elasticsearch.h3.H3.geoToH3(lat, lng, res);
}

Type guard

static boolean validResolution(int res) {
    return res >= 0 && res <= org.elasticsearch.h3.H3.MAX_H3_RES;
}

Try / catch

try {
    return H3.geoToH3(lat, lng, res);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("is out of range")) {
        throw new IllegalArgumentException("bad resolution " + res, e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling H3.geoToH3(lat, lng, res), geoToH3Address, northPolarH3(res), or southPolarH3(res) with res < 0 or res > 15. The most common entry point is geoToH3 with an unvalidated user resolution.

Common situations: User-supplied precision/zoom parameter passed straight to geoToH3 without clamping; default value left as -1 or 0 sentinel; confusion with a different library's resolution scale (e.g. 0..28 elsewhere).

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/df25078e143187a2. Report an issue: GitHub.