lionsoul2014/ip2region · error · ValueError

invalid ip address `{}`

Error message

invalid ip address `{}`

What it means

Python searcher type guard: the ip argument is neither str nor bytes (e.g. an int or None), so it cannot be parsed; the ValueError echoes the unusable value via {} formatting.

Source

Thrown at binding/python/ip2region/searcher.py:45

            self.__handle = io.open(db_path, "rb")
            self.vector_index = vector_index
            self.c_buffer = None

    def get_ip_version(self):
        return self.version

    def get_io_count(self):
        return self.__io_count

    def search(self, ip: Union[bytes, str]):
        # check and parse the string ip
        ip_bytes = None
        if isinstance(ip, str):
            ip_bytes = util.parse_ip(ip)
        elif isinstance(ip, bytes):
            ip_bytes = ip
        else:
            raise ValueError("invalid ip address `{}`".format(ip))

        # ip version check
        if len(ip_bytes) != self.version.byte_num:
            raise ValueError("invalid ip address `{}` ({} expected)".format(
                util.ip_to_string(ip_bytes), self.version.name))

        # reset the global io_count
        self.__io_count = 0

        # located the segment index block based on the vector index
        s_ptr, e_ptr, i0, i1 = 0, 0, ip_bytes[0], ip_bytes[1]
        idx = i0 * util.VectorIndexCols * util.VectorIndexSize + i1 * util.VectorIndexSize
        if self.vector_index != None:
            s_ptr = util.le_get_uint32(self.vector_index, idx)
            e_ptr = util.le_get_uint32(self.vector_index, idx + 4)
        elif self.c_buffer != None:
            offset = util.HeaderInfoLength + idx
            s_ptr = util.le_get_uint32(self.c_buffer, offset)

View on GitHub (pinned to c1a1fc7d59)

Solutions

  1. Pass the IP as a str ('1.2.3.4' / '2001:db8::1') or as 4/16 raw bytes
  2. Coerce or validate the input type (isinstance check) before calling search
  3. Reject non-string inputs at your API boundary

Example fix

# before
searcher.search(16909060)
# after
import ipaddress
searcher.search(str(ipaddress.ip_address(16909060)))
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(ip, (str, bytes)):
    raise ValueError(f"ip must be str or bytes, got {type(ip).__name__}")

Type guard

def is_ip_input(ip) -> bool:
    return isinstance(ip, (str, bytes))

Try / catch

try:
    region = searcher.search(ip)
except ValueError as e:
    if 'invalid ip address' in str(e):
        region = None  # unparseable input, skip/log
    else:
        raise

Prevention

When it happens

Trigger: Calling search() with an int, None, list, or other non-str/non-bytes object — e.g. passing the integer form of an IP or a boto of None from a failed lookup.

Common situations: Passing an int from a database/log field; passing a list of octets; forgetting that IPv4-mapped strings must be strings like '1.2.3.4'.

Related errors


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