lionsoul2014/ip2region · error

seek to get xdb file length: %w

Error message

seek to get xdb file length: %w

What it means

LoadContent seeks to offset 0 (to measure and stream the whole file) before io.ReadAll. If Seek(0,0) fails, the error is wrapped as 'seek to get xdb file length: %w'. It indicates the content could not be loaded because the handle is not seekable or the seek failed.

Source

Thrown at binding/golang/xdb/util.go:274

	if err != nil {
		return nil, fmt.Errorf("open xdb file `%s`: %w", dbFile, err)
	}
	defer handle.Close()

	vIndex, err := LoadVectorIndex(handle)
	if err != nil {
		return nil, err
	}

	return vIndex, nil
}

// LoadContent load the whole xdb content from the specified file handle
func LoadContent(handle io.ReadSeeker) ([]byte, error) {
	// seek to the head of the file
	_, err := handle.Seek(0, 0)
	if err != nil {
		return nil, fmt.Errorf("seek to get xdb file length: %w", err)
	}

	return io.ReadAll(handle)
}

// LoadContentFromFile load the whole xdb content from the specified db file path
func LoadContentFromFile(dbFile string) ([]byte, error) {
	handle, err := os.OpenFile(dbFile, os.O_RDONLY, 0600)
	if err != nil {
		return nil, fmt.Errorf("open xdb file `%s`: %w", dbFile, err)
	}
	defer handle.Close()

	cBuff, err := LoadContent(handle)
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to c1a1fc7d59)

Solutions

  1. Pass an io.ReadSeeker (*os.File, bytes.Reader); if the source is a stream, buffer it fully with io.ReadAll first and wrap in bytes.NewReader.
  2. Use LoadContentFromFS for embedded files instead of ad-hoc stream handling.
  3. Unwrap the error to find the underlying seek failure.

Example fix

// before
content, err := xdb.LoadContent(cmd.StdoutPipe()) // not seekable
// after
raw, _ := io.ReadAll(cmd.StdoutPipe())
content, err := xdb.LoadContent(bytes.NewReader(raw))
Defensive patterns

Strategy: type-guard

Validate before calling

func isSeekable(r io.Reader) bool {
    _, ok := r.(io.Seeker)
    return ok
}

Type guard

func asReadSeeker(r io.Reader) (io.ReadSeeker, bool) {
    s, ok := r.(io.ReadSeeker)
    return s, ok
}

Try / catch

cBuff, err := xdb.LoadContent(handle)
if err != nil {
    if strings.Contains(err.Error(), "seek to get xdb file length") {
        return fmt.Errorf("source is not seekable: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling LoadContent (or LoadContentFromFile-backed searchers) with a non-seekable io.ReadSeeker — pipes, network streams, stdin — or a broken/closed descriptor.

Common situations: Piping an xdb from curl into the program and passing the pipe reader directly; reading from a gzip stream without buffering; wrapping the file in a bufio.Reader (which is not a Seeker).

Related errors


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