lionsoul2014/ip2region · error · InetAddressException

invalid ip address (${version.name} expected)

Error message

invalid ip address (${version.name} expected)

What it means

Xdb Searcher instances are version-bound: a V4 searcher only accepts byte[4] IPs and a V6 searcher only byte[16]. The public search(byte[]) checks ip.length against version.bytes and throws InetAddressException when the IP version does not match the searcher's xdb version.

Source

Thrown at binding/java/src/main/java/org/lionsoul/ip2region/xdb/Searcher.java:115

        }
    }

    public Version getIPVersion() {
        return version;
    }

    public int getIOCount() {
        return ioCount;
    }

    public String search(String ipStr) throws Exception {
        return search(Util.parseIP(ipStr));
    }

    public String search(byte[] ip) throws IOException, InetAddressException {
        // ip version check
        if (ip.length != version.bytes) {
            throw new InetAddressException("invalid ip address ("+version.name+" expected)");
        }

        // reset the global counter
        this.ioCount = 0;

        // locate the segment index block based on the vector index
        long sPtr = 0, ePtr = 0;
        int il0 = (int) (ip[0] & 0xFF);
        int il1 = (int) (ip[1] & 0xFF);
        int idx = il0 * VectorIndexCols * VectorIndexSize + il1 * VectorIndexSize;
        // System.out.printf("il0: %d, il1: %d, idx: %d\n", il0, il1, idx);
        if (vectorIndex != null) {
            sPtr = LittleEndian.getUint32(vectorIndex, idx);
            ePtr = LittleEndian.getUint32(vectorIndex, idx + 4);
        } else if (contentBuff != null) {
            sPtr = contentBuff.getUint32(HeaderInfoLength + idx);
            ePtr = contentBuff.getUint32(HeaderInfoLength + idx + 4);
        } else {

View on GitHub (pinned to c1a1fc7d59)

Solutions

  1. Route the IP to the searcher matching its version: ip.length==4 -> v4 searcher, ip.length==16 -> v6 searcher
  2. Use Ip2Region.search(String) or a length check on the raw bytes to pick the correct searcher
  3. Create/keep both a V4 and a V6 searcher and dispatch on array length

Example fix

// before
String r = v6Searcher.search(ipBytes); // ipBytes.length == 4
// after
String r = (ipBytes.length == 4) ? v4Searcher.search(ipBytes) : v6Searcher.search(ipBytes);
Defensive patterns

Strategy: type-guard

Validate before calling

if (ip.length != expectedVersionBytes) {
    throw new IllegalArgumentException("searcher version mismatch");
}

Type guard

static boolean matchesSearcherVersion(byte[] ip, Version v) {
    return ip != null && ip.length == v.bytes;
}

Try / catch

try {
    return searcher.search(ip);
} catch (InetAddressException e) {
    log.warn("ip version mismatch for searcher", e);
    return alternateSearcher(ip);
}

Prevention

When it happens

Trigger: Calling search on a searcher built via asV4() with a 16-byte IPv6 array, or via asV6() with a 4-byte IPv4 array.

Common situations: Dual-stack applications routing all incoming addresses through a single V4 searcher; using the wrong Ip2Region field (v4 vs v6) after a code refactor.

Related errors


AI-assisted analysis of lionsoul2014/ip2region@c1a1fc7d59 (2026-09-02). Data as JSON: /api/errors/73f8fbad18b5739c. Report an issue: GitHub.