lionsoul2014/ip2region · error

loading header

Error message

loading header: %w

What it means

Verify validates an xdb file handle and starts by loading the file's header via LoadHeader; if that read/parse fails, the underlying error is wrapped as "loading header". This typically indicates the file is too small, unreadable, or not an xdb file at all.

Solutions

  1. Check the file exists, is a regular file, and is readable by the current user
  2. Re-download the xdb file and confirm its size/checksum
  3. Ensure the handle is opened successfully and not closed before Verify
  4. Confirm the file is actually an xdb v2/v3 data file, not HTML from a failed download

Example fix

// before
f, _ := os.Open("bad.xdb")
err := xdb.Verify(f) // loading header: ...
// after
stat, err := os.Stat("bad.xdb")
if err != nil || stat.Size() < 256 { log.Fatal("xdb missing or truncated") }
err = xdb.VerifyFromFile("bad.xdb")
Defensive patterns

Strategy: validation

Validate before calling

func xdbReadable(path string) error {
    info, err := os.Stat(path)
    if err != nil { return err }
    if !info.Mode().IsRegular() { return fmt.Errorf("%s is not a regular file", path) }
    if info.Size() < 256 { return fmt.Errorf("%s too small (%d bytes) to be an xdb file", path, info.Size()) }
    f, err := os.Open(path)
    if err != nil { return err }
    defer f.Close()
    return nil
}

Try / catch

if err := xdb.VerifyFromFile(dbPath); err != nil {
    return fmt.Errorf("xdb %s failed verification: %w", dbPath, err)
}

Prevention

When it happens

Trigger: Calling xdb.Verify(handle) or VerifyFromFile on a file smaller than the header, with wrong permissions, an empty file, or a random/corrupted file; passing a closed *os.File.

Common situations: Pointing the tool at a wrong path that resolved to a directory or empty placeholder; partially downloaded xdb; file corrupted in transit; running the check as a user lacking read permission.

Related errors


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

Appendix: source

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

func IPMiddle(sip, eip []byte) ([]byte, error) {
	buf, err := IPAdd(sip, eip)
	if err != nil {
		return []byte{}, fmt.Errorf("IPSub(%s, %s): %w", IP2String(sip), IP2String(eip), err)
	}

	return IPHalf(buf), nil
}

// Verify if the current Searcher could be used to search the specified xdb file.
// Why do we need this check ?
// The future features of the xdb impl may cause the current searcher not able to work properly.
//
// @Note: You Just need to check this ONCE when the service starts
// Or use another process (eg, A command) to check once Just to confirm the suitability.
func Verify(handle *os.File) error {
	header, err := LoadHeader(handle)
	if err != nil {
		return fmt.Errorf("loading header: %w", err)
	}

	// get the runtime ptr bytes
	runtimePtrBytes := 0
	switch header.Version {
	case Structure20:
		runtimePtrBytes = 4
	case Structure30:
		runtimePtrBytes = header.RuntimePtrBytes
	default:
		return fmt.Errorf("invalid version: %d", header.Version)
	}

	// 1, confirm the xdb file size.
	// to sure that the MaxFilePointer does no overflow
	stat, err := handle.Stat()
	if err != nil {
		return fmt.Errorf("file stat: %w", err)

View on GitHub (pinned to c1a1fc7d59)