lionsoul2014/ip2region · error
seek to the header: %w
Error message
seek to the header: %w
What it means
LoadHeader seeks the given io.ReadSeeker to offset 0 before reading the 256-byte xdb header. If the Seek(0,0) call fails (e.g. the handle is not seekable or an underlying read error occurs), the error is wrapped as 'seek to the header: %w'. It signals that the header could not be located, not that the header content is invalid.
Source
Thrown at binding/golang/xdb/util.go:191
return nil
}
// VerifyFromFile check Verify for details
func VerifyFromFile(dbFile string) error {
handle, err := os.OpenFile(dbFile, os.O_RDONLY, 0600)
if err != nil {
return fmt.Errorf("open xdb file `%s`: %w", dbFile, err)
}
defer handle.Close()
return Verify(handle)
}
// LoadHeader load the header info from the specified handle
func LoadHeader(handle io.ReadSeeker) (*Header, error) {
_, err := handle.Seek(0, 0)
if err != nil {
return nil, fmt.Errorf("seek to the header: %w", err)
}
var buff = make([]byte, HeaderInfoLength)
rLen, err := handle.Read(buff)
if err != nil {
return nil, err
}
if rLen != len(buff) {
return nil, fmt.Errorf("incomplete read: readed bytes should be %d", len(buff))
}
return NewHeader(buff)
}
// LoadHeaderFromFile load header info from the specified db file path
func LoadHeaderFromFile(dbFile string) (*Header, error) {
handle, err := os.OpenFile(dbFile, os.O_RDONLY, 0600)View on GitHub (pinned to c1a1fc7d59)
Solutions
- Pass an io.ReadSeeker such as *os.File, bytes.Reader, or bytes.Buffer — never a pipe or network stream.
- Load the whole content with LoadContentFromFile / LoadContentFromFS instead of streaming a non-seekable source.
- Unwrap the wrapped error with errors.Unwrap or errors.As to see the underlying cause and fix it.
Example fix
// before header, err := xdb.LoadHeader(httpResp.Body) // Body is not a ReadSeeker // after body, _ := io.ReadAll(httpResp.Body) header, err := xdb.LoadHeader(bytes.NewReader(body)
Defensive patterns
Strategy: type-guard
Validate before calling
func isSeekable(r io.Reader) bool {
_, ok := r.(io.Seeker)
return ok
}
// call site: if !isSeekable(myReader) { ... load via LoadContentFromBuff instead ... } Type guard
func asReadSeeker(r io.Reader) (io.ReadSeeker, bool) {
s, ok := r.(io.ReadSeeker)
return s, ok
} Try / catch
header, err := xdb.LoadHeader(handle)
if err != nil {
var seekErr *fs.PathError
if errors.As(err, &seekErr) {
// handle is not seekable; fall back to buffering
}
return fmt.Errorf("header load failed: %w", err)
} Prevention
- Only pass io.ReadSeeker types (*os.File, bytes.Reader, bytes.Buffer) to Load* functions
- For network/stream sources, buffer fully with io.ReadAll then wrap with bytes.NewReader
- Prefer LoadContentFromFile/LoadContentFromFS over manual handle construction
When it happens
Trigger: Calling LoadHeader (directly or via LoadHeaderFromFile, Verify, or Searcher creation) with a handle whose Seek to 0 fails — typically a non-seekable reader such as an HTTP response body, a pipe, os.Stdin, or a bytes.Reader already consumed without rewind support.
Common situations: Passing a network stream or io.Pipe to LoadHeader instead of an *os.File or bytes.Reader; a corrupted or closed file descriptor underlying the handle; wrapping a file in a reader that does not implement io.Seeker.
Related errors
- seek to vector index: %w
- seek to get xdb file length: %w
- incomplete read: readed bytes should be %d
- invalid input buffer
- read vector index block at %d: %w
AI-assisted analysis of lionsoul2014/ip2region@c1a1fc7d59 (2026-09-02).
Data as JSON: /api/errors/44d80b398fa74961.
Report an issue: GitHub.