lionsoul2014/ip2region · error

seek to %d: %w

Error message

seek to %d: %w

What it means

Go xdb searcher file-mode read: dbReader.Seek to the required offset failed before reading; the wrapped system error is typically an I/O fault or an offset beyond EOF, both signs of a truncated or damaged xdb.

Source

Thrown at binding/golang/xdb/searcher.go:216

		return "", fmt.Errorf("read region at %d: %w", dataPtr, err)
	}

	return string(regionBuff), nil
}

// do the data read operation based on the setting.
// content buffer first or will read from the file.
// this operation will invoke the Seek for file based read.
func (s *Searcher) read(offset int64, buff []byte) error {
	if s.contentBuff != nil {
		cLen := copy(buff, s.contentBuff[offset:])
		if cLen != len(buff) {
			return fmt.Errorf("incomplete read: readed bytes should be %d", len(buff))
		}
	} else {
		_, err := s.dbReader.Seek(offset, 0)
		if err != nil {
			return fmt.Errorf("seek to %d: %w", offset, err)
		}

		s.ioCount++
		rLen, err := s.dbReader.Read(buff)
		if err != nil {
			return fmt.Errorf("handle read: %w", err)
		}

		if rLen != len(buff) {
			return fmt.Errorf("incomplete read: readed bytes should be %d", len(buff))
		}
	}

	return nil
}

View on GitHub (pinned to c1a1fc7d59)

Solutions

  1. Ensure the searcher's file is still open (don't call Close on the file/xdb while searches are in flight).
  2. Verify xdb integrity — corrupted index/header can produce invalid offsets.
  3. Reopen the searcher/file and retry once on transient I/O errors.
  4. Inspect err.Unwrap() for the syscall-level cause (EBADF, ESPIPE, etc.).

Example fix

// before
file.Close() // ... later
region, _ := searcher.Search(ctx, ip) // seek on closed file
// after
region, err := searcher.Search(ctx, ip)
if err != nil { return err }
// close the file only when done searching
file.Close()
Defensive patterns

Strategy: try-catch

Validate before calling

if f == nil { return errors.New("xdb file not open") }
if offset < 0 { return errors.New("negative read offset — corrupt xdb?") }

Try / catch

region, err := searcher.Search(ctx, ip)
if err != nil {
    var pErr *fs.PathError
    if errors.As(errors.Unwrap(err), &pErr) || strings.Contains(err.Error(), "seek to") {
        searcher, err = reopenSearcher() // file handle likely closed/stale
    }
    return err
}

Prevention

When it happens

Trigger: Negative or out-of-range offset passed to Seek (corrupted pointers from a corrupt xdb); the underlying file was closed; the file descriptor is invalid after the file was deleted/replaced on some filesystems.

Common situations: Keeping a searcher open after Close() was called; corrupted xdb header producing wild offsets; reading from a file on a flaky network mount.

Related errors


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