lionsoul2014/ip2region · error · Exception

incomplete read: read bytes should be {$len}

Error message

incomplete read: read bytes should be {$len}

What it means

fread() succeeded but returned fewer bytes than requested ($len). A short read on a well-formed xdb means the file is truncated or the offset is past the end, so the library refuses to return partial data.

Source

Thrown at binding/php/xdb/Searcher.class.php:567

        // check the in-memory buffer first
        if ($this->contentBuff != null) {
            return substr($this->contentBuff, $offset, $len);
        }

        // read from the file
        $r = fseek($this->handle, $offset);
        if ($r == -1) {
            throw new Exception("failed to fseek to {$offset}");
        }

        $this->ioCount++;
        $buff = fread($this->handle, $len);
        if ($buff === false) {
            throw new Exception("failed to fread from {$len}");
        }

        if (strlen($buff) != $len) {
            throw new Exception("incomplete read: read bytes should be {$len}");
        }

        return $buff;
    }

}

View on GitHub (pinned to c1a1fc7d59)

Solutions

  1. Re-download/regenerate the xdb file and verify its size and checksum against the source
  2. Confirm the xdb structure version is compatible with the library version you run (v2/v3)
  3. Run the library's structure verification (e.g. util verify) against the file before searching

Example fix

// before
$searcher = ...newWithFileOnly('/path/truncated.xdb');
// after
// re-copy full file, then verify:
$searcher = ...newWithFileOnly('/path/full.xdb');
// or check: filesize($dbFile) matches the publisher's expected size
Defensive patterns

Strategy: validation

Validate before calling

$expected = 11; // check header/expected size from your xdb source
if (filesize($dbFile) < $expected) {
    throw new RuntimeException("xdb file truncated: {$dbFile}");
}

Try / catch

try {
    $region = $searcher->search($ip);
} catch (\Exception $e) {
    if (strpos($e->getMessage(), 'incomplete read') !== false) {
        // file truncated/corrupt: re-fetch the xdb and rebuild the searcher
        $region = null;
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: search()/read() where strlen($buff) != $len — reading past EOF because the xdb file is truncated/corrupted, or the data was written by an incompatible structure version.

Common situations: Partially downloaded or interrupted copy of the xdb file; wrong xdb file version paired with a newer/older searcher; file replaced mid-search with a smaller file.

Related errors


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