lionsoul2014/ip2region · error

v4 searcher pool already closed

Error message

v4 searcher pool already closed

What it means

Go service lifecycle error: v4Search tried to borrow a searcher from the v4 pool but BorrowSearcher returned nil, which happens after the pool has been closed (Close drains and shuts down the channel). Searching on a closed service is rejected by this sentinel.

Source

Thrown at binding/golang/service/ip2region.go:157

		return ip2r.v6Search(ipBytes)
	} else {
		return "", fmt.Errorf("invalid byte ip address with len=%d", l)
	}
}

func (ip2r *Ip2Region) v4Search(ipBytes []byte) (string, error) {
	if ip2r.v4InMemSearcher != nil {
		return ip2r.v4InMemSearcher.Search(ipBytes)
	}

	// v4 search is disabled
	if ip2r.v4Pool == nil {
		return "", nil
	}

	v4Searcher := ip2r.v4Pool.BorrowSearcher()
	if v4Searcher == nil {
		return "", fmt.Errorf("v4 searcher pool already closed")
	}
	defer ip2r.v4Pool.ReturnSearcher(v4Searcher)
	return v4Searcher.Search(ipBytes)
}

func (ip2r *Ip2Region) v6Search(ipBytes []byte) (string, error) {
	if ip2r.v6InMemSearcher != nil {
		return ip2r.v6InMemSearcher.Search(ipBytes)
	}

	// v6 search is disabled
	if ip2r.v6Pool == nil {
		return "", nil
	}

	v6Searcher := ip2r.v6Pool.BorrowSearcher()
	if v6Searcher == nil {
		return "", fmt.Errorf("v6 searcher pool already closed")

View on GitHub (pinned to c1a1fc7d59)

Solutions

  1. Do not call Search after Ip2Region.Close; create a new service instead
  2. Guard concurrent shutdown vs. in-flight searches with a WaitGroup or context
  3. Return a typed sentinel error so callers can distinguish closed-pool from real failures
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at binding/golang/service/ip2region.go:157 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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