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

  1. Pass an io.ReadSeeker such as *os.File, bytes.Reader, or bytes.Buffer — never a pipe or network stream.
  2. Load the whole content with LoadContentFromFile / LoadContentFromFS instead of streaming a non-seekable source.
  3. 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

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


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