lionsoul2014/ip2region · error · Exception

failed to fread from {$len}

Error message

failed to fread from {$len}

What it means

After a successful fseek, the searcher reads $len bytes with fread(); fread() returning false means the read itself failed at the OS/PHP level. The library throws to signal that the xdb index could not be read.

Source

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

    }

    // read specified bytes from the specified index
    private function read($offset, $len) {
        // 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-create the searcher (newWithFileOnly or newWithBuffer) so a fresh, readable handle is used
  2. Check file permissions and that the xdb file still exists and is readable by the PHP process
  3. Use newWithBuffer()/full-buffer mode to read the whole file once and avoid repeated I/O failures during search

Example fix

// before
$handle = fopen($dbFile, 'rb'); // unreadable perms
// after
$searcher = \ip2region\XdbSearcher::newWithBuffer(file_get_contents($dbFile));
Defensive patterns

Strategy: try-catch

Validate before calling

if (!is_readable($dbFile)) {
    throw new RuntimeException("xdb file not readable: {$dbFile}");
}

Try / catch

try {
    $region = $searcher->search($ip);
} catch (\Exception $e) {
    if (strpos($e->getMessage(), 'failed to fread') !== false) {
        $region = null; // log and mark service degraded / reload searcher
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: search()/read() on a file-backed searcher where fread() returns false — closed or unreadable handle, disk/permission error, or stream in an error state.

Common situations: File deleted or permissions changed after the searcher was created; reading from a network mount that dropped; handle exhausted by an earlier error.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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