lionsoul2014/ip2region · error
read segment index at %d: %w
Error message
read segment index at %d: %w
What it means
Go xdb searcher: reading one fixed-size segment-index row (during the binary search over the index block) failed via the internal read(); the wrapped error is a seek/read/short-read failure against the file or content buffer, indicating a truncated or corrupt xdb.
Source
Thrown at binding/golang/xdb/searcher.go:174
// fmt.Printf("sPtr=%d, ePtr=%d\n", sPtr, ePtr)
// @Note: ptr validate, zero ptr means source data missing
// so we could just stop here and return an empty string.
if sPtr == 0 || ePtr == 0 {
return "", nil
}
// binary search the segment index to get the region
var bytes, dBytes = len(ipBytes), len(ipBytes) << 1
var segIndexSize = uint32(s.version.SegmentIndexSize)
var dataLen, dataPtr = 0, uint32(0)
var buff = make([]byte, segIndexSize)
var l, h = 0, int((ePtr - sPtr) / segIndexSize)
for l <= h {
m := (l + h) >> 1
p := sPtr + uint32(m)*segIndexSize
err := s.read(int64(p), buff)
if err != nil {
return "", fmt.Errorf("read segment index at %d: %w", p, err)
}
// decode the data step by step to reduce the unnecessary operations
if s.version.IPCompare(ipBytes, buff[0:bytes]) < 0 {
h = m - 1
} else if s.version.IPCompare(ipBytes, buff[bytes:dBytes]) > 0 {
l = m + 1
} else {
dataLen = int(binary.LittleEndian.Uint16(buff[dBytes:]))
dataPtr = binary.LittleEndian.Uint32(buff[dBytes+2:])
break
}
}
// fmt.Printf("dataLen: %d, dataPtr: %d\n", dataLen, dataPtr)
if dataLen == 0 {
return "", nil
}View on GitHub (pinned to c1a1fc7d59)
Solutions
- Verify file integrity (size vs header end-pointer; compare checksum if available) and re-download the xdb.
- Ensure content-buffer searchers get the entire file, matching header.StartIndexPtr/HeaderInfoLength+IndexSize expectations.
- Check disk space / permissions for file-based searchers.
- Inspect the wrapped OS error to distinguish seek failure from short read.
Example fix
// before
st, _ := os.Stat(path)
// no size check, searcher reads garbage index
// after
st, err := os.Stat(path)
if err != nil { return err }
hdr, err := xdb.LoadHeaderFromFile(path)
if err != nil { return err }
if int64(hdr.Length) > st.Size() {
return fmt.Errorf("xdb truncated: have %d, need %d", st.Size(), hdr.Length)
} Defensive patterns
Strategy: validation
Validate before calling
fi, _ := os.Stat(xdbPath)
hdr, err := xdb.LoadHeaderFromFile(xdbPath)
if err != nil { return err }
if fi.Size() < int64(hdr.Length) {
return fmt.Errorf("xdb truncated: %d < %d", fi.Size(), hdr.Length)
} Try / catch
region, err := searcher.Search(ctx, ip)
if err != nil {
if strings.Contains(err.Error(), "read segment index") {
return nil, fmt.Errorf("xdb index corrupt — regenerate the xdb file")
}
return err
} Prevention
- Compare file size against header.Length after download.
- Prefer LoadContentFromFile-based searchers to avoid mid-search I/O failures.
- Keep a checksum of the xdb build and verify on deploy.
- Never mix buffers/header from different xdb builds.
When it happens
Trigger: File-based read failure (bad seek/short read) at segment index offset p; a corrupted or truncated xdb whose index area is shorter than the header's start/end pointers claim; content buffer missing the index tail.
Common situations: Truncated download cutting off the index section; corrupted xdb produced by a failed maker run; searching an xdb loaded from a partially cached buffer.
Related errors
- invalid input buffer
- read vector index block at %d: %w
- read region at %d: %w
- incomplete read: readed bytes should be %d
- seek to %d: %w
AI-assisted analysis of lionsoul2014/ip2region@c1a1fc7d59 (2026-09-02).
Data as JSON: /api/errors/ed055f53168dc3e2.
Report an issue: GitHub.