XX-net/XX-Net · error · ValueError

%s file format error

Error message

%s file format error

What it means

Raised while loading the China IP database file (cn_ipdb) in the smart router's ip_region module. The loader reads a fixed 224*4-byte index and data_len bytes of IP ranges, then expects the 3-byte trailer b'end'. If that trailer is missing the file is judged corrupt or in an unexpected format and a ValueError('%s file format error') is raised from load_db during __init__.

Source

Thrown at code/default/smart_router/local/ip_region.py:54

    def __init__(self):
        self.cn = b"CN"
        self.ipdb = self.load_db()

    def load_db(self):
        if not os.path.isfile(self.cn_ipdb):
            self.generate_db()

        with open(self.cn_ipdb, 'rb') as f:
            # 读取 IP 范围数据长度 BE Ulong -> int
            data_len, = struct.unpack('>L', f.read(4))
            # 读取索引数据
            index = f.read(224 * 4)
            # 读取 IP 范围数据
            data = f.read(data_len)
            # 简单验证结束
            if f.read(3) != b'end':
                raise ValueError('%s file format error' % self.cn_ipdb)
            # 读取更新信息
            self.update = f.read().decode('ascii')
        # 格式化并缓存索引数据
        # 使用 struct.unpack 一次性分割数据效率更高
        # 每 4 字节为一个索引范围 fip:BE short -> int,对应 IP 范围序数
        self.index = struct.unpack('>' + 'h' * (224 * 2), index)
        # 每 8 字节对应一段直连 IP 范围和一段非直连 IP 范围
        self.raw_data = data

    def check_ip(self, ip):
        ip = utils.to_str(ip)
        if ":" in ip:
            return False

        #转换 IP 为 BE Uint32,实际类型 bytes
        nip = socket.inet_aton(ip)
        #确定索引范围
        index = self.index

View on GitHub (pinned to cfa5bc17b6)

Solutions

  1. Re-download the China IP database file so it is complete and matches the expected format
  2. Verify the file size: it must contain 224*4 index bytes + data_len + 3-byte 'end' trailer; replace if truncated
  3. Check self.cn_ipdb path configuration points to the correct data file
  4. If format changed upstream, update the reader in code/default/smart_router/local/ip_region.py to match the new layout

Example fix

# before
if f.read(3) != b'end':
    raise ValueError('%s file format error' % self.cn_ipdb)

# after (self-heal: re-download once before failing)
if f.read(3) != b'end':
    try:
        download_cn_ipdb(self.cn_ipdb)
        return self.load_db()
    except Exception:
        raise ValueError('%s file format error' % self.cn_ipdb)
Defensive patterns

Strategy: validation

Validate before calling

import os
EXPECTED_MIN = 224*4 + 3
def ipdb_ok(path):
    if not os.path.isfile(path) or os.path.getsize(path) < EXPECTED_MIN:
        return False
    with open(path,'rb') as f:
        f.seek(-3, os.SEEK_END)
        return f.read(3) == b'end'

Try / catch

try:
    region = IpRegion()
except ValueError as e:
    if 'file format error' in str(e):
        re_download_ipdb(); region = IpRegion()
    else:
        raise

Prevention

When it happens

Trigger: Instantiating the IpRegion class when data/cn_ipdb.dat (or whatever path self.cn_ipdb points to) is truncated, corrupted, from an incompatible ipdb version, or is an HTML error page saved in place of the real database.

Common situations: Interrupted/partial download of the ipdb file, wrong file placed at the configured path, version mismatch between the ipdb data file and the reader code expecting the 'end' marker layout.

Related errors


AI-assisted analysis of XX-net/XX-Net@cfa5bc17b6 (2026-08-27). Data as JSON: /api/errors/c99b4ff08d29e91f. Report an issue: GitHub.