lionsoul2014/ip2region · error · Exception
failed to fseek to {$offset}
Error message
failed to fseek to {$offset} What it means
During a file-based (non-full-buffer) search, the searcher repositions the file handle with fseek() to the computed offset. A return of -1 means the seek failed, so the library cannot read the index/data block and aborts the search.
Source
Thrown at binding/php/xdb/Searcher.class.php:557
if ($dataLen == 0) {
return "";
}
// load and return the region data
return $this->read($dataPtr, $dataLen);
}
// 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
- Recreate the Searcher via Searcher::newWithFileOnly() (or load the file into a buffer with newWithBuffer()) to get a fresh, valid handle
- Confirm the xdb file path is correct and the file is not truncated or corrupted
- Avoid sharing/closing the underlying file handle while searching; if resource limits are an issue use the buffered or vector-index load modes
Example fix
// before $searcher = new Searcher($dbFile, $header, $handle); // stale/closed handle // after $searcher = \ip2region\XdbSearcher::newWithFileOnly($dbFile);
Defensive patterns
Strategy: retry
Validate before calling
if (!is_resource($searcher->getHandle()) || ftell($searcher->getHandle()) === false) {
$searcher = Searcher::newWithFileOnly($dbFile);
} Try / catch
try {
$region = $searcher->search($ip);
} catch (\Exception $e) {
if (strpos($e->getMessage(), 'failed to fseek') !== false) {
$searcher = Searcher::newWithFileOnly($dbFile); // rebuild handle, retry once
$region = $searcher->search($ip);
} else {
throw $e;
}
} Prevention
- Never close or rewind the xdb file handle while the searcher is alive
- Prefer newWithBuffer()/vector-index mode to minimize runtime seeks
- Recreate the searcher per long-lived process instead of sharing one across requests that manage handles
When it happens
Trigger: Calling search() with a file handle whose fseek() to the internal offset returns -1 — typically an invalid/closed handle, or an offset beyond what the handle supports.
Common situations: The xdb file was closed or reopened elsewhere mid-search; passing the wrong resource type or a handle opened in a mode that disallows seeking; corrupted xdb producing out-of-range offsets.
Related errors
- failed to fread from {$len}
- incomplete read: read bytes should be {$len}
- incomplete read (${rBytes} read, ${header.HeaderInfoLength}
- incomplete read (${rBytes} read, ${vBytes} expected)
- incomplete read (${rBytes} read, ${stats.size} expected)
AI-assisted analysis of lionsoul2014/ip2region@c1a1fc7d59 (2026-09-02).
Data as JSON: /api/errors/9f7cd9b4ea541501.
Report an issue: GitHub.