lionsoul2014/ip2region · error

invalid version: %d

Error message

invalid version: %d

What it means

Verify reads the header's Version field and only supports Structure20 (v2) and Structure30 (v3); any other version value fails with "invalid version". This guards against searching xdb files written by incompatible writer versions.

Source

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

// 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)
	}

	maxFilePtr := (int64(1) << (runtimePtrBytes * 8)) - 1
	if stat.Size() > maxFilePtr {
		return fmt.Errorf("xdb file exceeds the maximum supported bytes: %d", maxFilePtr)
	}

	return nil
}

// VerifyFromFile check Verify for details

View on GitHub (pinned to c1a1fc7d59)

Solutions

  1. Upgrade the xdb Go binding to a version that supports Structure30 (v3) files
  2. Regenerate or download the data file in the format matching your binding version
  3. Check header.Version against xdb.Structure20/Structure30 before calling Verify
  4. Re-download the file if the version value looks corrupted (e.g. huge or 0)

Example fix

// before
// old binding: only Structure20
db, _ := xdb.LoadHeaderFromFile("v3.xdb")
err := xdb.Verify(f) // invalid version: 3
// after
// go get -u github.com/lionsoul2014/ip2region/binding/golang
header, _ := xdb.LoadHeaderFromFile("v3.xdb")
fmt.Println(header.Version) // Structure30
err = xdb.VerifyFromFile("v3.xdb")
Defensive patterns

Strategy: validation

Validate before calling

header, err := xdb.LoadHeaderFromFile("ip2region.xdb")
if err != nil { return err }
if header.Version != xdb.Structure20 && header.Version != xdb.Structure30 {
    return fmt.Errorf("unsupported xdb version %d; regenerate the data file", header.Version)
}

Type guard

func supportedVersion(v int) bool {
    return v == xdb.Structure20 || v == xdb.Structure30
}

Try / catch

if err := xdb.VerifyFromFile(dbPath); err != nil {
    if strings.Contains(err.Error(), "invalid version") {
        return fmt.Errorf("re-download or regenerate %s in a supported format: %w", dbPath, err)
    }
    return err
}

Prevention

When it happens

Trigger: Opening an xdb produced by a newer/older writer whose header version is not 2 or 3; a corrupted header where the version byte is garbage (often surfacing here after a partial header parse); mixing binding versions where the Go binding predates Structure30.

Common situations: Upgrading the data file to the v3 format while the application pins an old ip2region Go binding; hand-merged or edited xdb files; corrupted downloads where the header bytes are wrong.

Related errors


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