lionsoul2014/ip2region · error · Exception
invalid ip address ({$this->version->name} expected)
Error message
invalid ip address ({$this->version->name} expected) What it means
The PHP Searcher throws this when the byte length of the IP passed to searchByBytes() does not match the byte count required by the xdb file's IP version (e.g. 4 bytes for IPv4, 16 for IPv6). The library checks the version up front because searching with the wrong IP size would corrupt index lookups.
Source
Thrown at binding/php/xdb/Searcher.class.php:483
*/
public function search($ip) {
$ipBytes = Util::parseIP($ip);
if ($ipBytes == null) {
throw new Exception("invalid ip address `{$ip}`");
}
return $this->searchByBytes($ipBytes);
}
/**
* find the region info for the specified binary ip bytes returned by #parseIP.
*
* @throws Exception
*/
public function searchByBytes($ipBytes) {
// ip version check
if (strlen($ipBytes) != $this->version->bytes) {
throw new Exception("invalid ip address ({$this->version->name} expected)");
}
// reset the global counter
$this->ioCount = 0;
// locate the segment index block based on the vector index
$il0 = ord($ipBytes[0]) & 0xFF;
$il1 = ord($ipBytes[1]) & 0xFF;
$idx = $il0 * VectorIndexCols * VectorIndexSize + $il1 * VectorIndexSize;
if ($this->vectorIndex != null) {
$sPtr = Util::le_getUint32($this->vectorIndex, $idx);
$ePtr = Util::le_getUint32($this->vectorIndex, $idx + 4);
} else if ($this->contentBuff != null) {
$sPtr = Util::le_getUint32($this->contentBuff, HeaderInfoLength + $idx);
$ePtr = Util::le_getUint32($this->contentBuff, HeaderInfoLength + $idx + 4);
} else {
// read the vector index block
$buff = $this->read(HeaderInfoLength + $idx, 8);View on GitHub (pinned to c1a1fc7d59)
Solutions
- Convert the IP string to raw bytes with the library's helper (e.g. inet_pton / util parse) before calling searchByBytes()
- Verify the xdb file's IP version matches the addresses you search; load an IPv6-capable (v3) xdb if you need IPv6
- Use the higher-level search($ip) entry point which parses and validates the IP string for you
Example fix
// before
$searcher->searchByBytes('1.2.3.4');
// after
$bytes = inet_pton('1.2.3.4'); // 4 raw bytes for IPv4
$searcher->searchByBytes($bytes); Defensive patterns
Strategy: validation
Validate before calling
$bytes = is_string($ip) ? (filter_var($ip, FILTER_VALIDATE_IP) ? inet_pton($ip) : null) : $ip;
if ($bytes === null || strlen($bytes) !== $this->version->bytes) {
throw new InvalidArgumentException("ip does not match {$this->version->name}");
} Type guard
function isIpBytesFor(string $bytes, object $version): bool {
return strlen($bytes) === $version->bytes;
} Try / catch
try {
$region = $searcher->searchByBytes($bytes);
} catch (\Exception $e) {
if (strpos($e->getMessage(), 'invalid ip address') !== false) {
$region = null; // treat as unresolvable input
} else {
throw $e;
}
} Prevention
- Always feed IPs through the library's string search() instead of crafting bytes yourself
- Check the xdb file's version once at startup and keep separate searchers for v4/v6
- Unit-test with one known IPv4 and one known IPv6 address
When it happens
Trigger: Calling Searcher::searchByBytes() with a byte string whose strlen() differs from $this->version->bytes — e.g. passing 16-byte IPv6 bytes to a v4-only xdb searcher, or 4-byte bytes to a v6 searcher, or a non-raw binary string.
Common situations: Opening an IPv4 xdb file but searching IPv6 addresses (or vice versa); passing a hex/human-readable string like '1.2.3.4' instead of the packed 4-byte form; mixing up a v1 (IPv4) file with the v3 (IPv6-capable) searcher API.
Related errors
- invalid byte ip address with length=${ipBytes.length}
- invalid ip address `${ip}`
- invalid ip address `{}`
- invalid ip address `{}` ({} expected)
- invalid ip address: %s
AI-assisted analysis of lionsoul2014/ip2region@c1a1fc7d59 (2026-09-02).
Data as JSON: /api/errors/8b58cff92b8d9b9f.
Report an issue: GitHub.