{"record":{"id":"d52ec915e49e5bb1","repo":"lionsoul2014/ip2region","slug":"read-region-at-d-w","errorCode":null,"errorMessage":"read region at %d: %w","messagePattern":"read region at (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"binding/golang/xdb/searcher.go","lineNumber":198,"sourceCode":"\t\t} else if s.version.IPCompare(ipBytes, buff[bytes:dBytes]) > 0 {\n\t\t\tl = m + 1\n\t\t} else {\n\t\t\tdataLen = int(binary.LittleEndian.Uint16(buff[dBytes:]))\n\t\t\tdataPtr = binary.LittleEndian.Uint32(buff[dBytes+2:])\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// fmt.Printf(\"dataLen: %d, dataPtr: %d\\n\", dataLen, dataPtr)\n\tif dataLen == 0 {\n\t\treturn \"\", nil\n\t}\n\n\t// load and return the region data\n\tvar regionBuff = make([]byte, dataLen)\n\terr = s.read(int64(dataPtr), regionBuff)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"read region at %d: %w\", dataPtr, err)\n\t}\n\n\treturn string(regionBuff), nil\n}\n\n// do the data read operation based on the setting.\n// content buffer first or will read from the file.\n// this operation will invoke the Seek for file based read.\nfunc (s *Searcher) read(offset int64, buff []byte) error {\n\tif s.contentBuff != nil {\n\t\tcLen := copy(buff, s.contentBuff[offset:])\n\t\tif cLen != len(buff) {\n\t\t\treturn fmt.Errorf(\"incomplete read: readed bytes should be %d\", len(buff))\n\t\t}\n\t} else {\n\t\t_, err := s.dbReader.Seek(offset, 0)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"seek to %d: %w\", offset, err)","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/lionsoul2014/ip2region/blob/c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1/binding/golang/xdb/searcher.go#L180-L216","documentation":"Go xdb searcher: after locating the matching segment, reading the region data at dataPtr failed in read(); the wrapped cause (seek/read error or short read) points to file truncation or corruption at the data offset.","triggerScenarios":"File read/seek failure at dataPtr; xdb truncated so the data section is missing; corrupted index block yielding an out-of-range dataPtr (e.g., mixing buffers from two different xdb files).","commonSituations":"Partially downloaded xdb (index intact, data tail missing); pairing a header/content buffer from one xdb version with a searcher/file of another; storage errors on network mounts.","solutions":["Re-download or regenerate the xdb file — the data section is truncated or corrupt.","Ensure header, content buffer, and file all come from the SAME xdb build/version.","For file searchers, verify the file wasn't replaced while open; reopen the searcher.","Check the wrapped OS error for permission/EOF causes."],"exampleFix":"// before\nheader, _ := xdb.LoadHeaderFromFile(oldPath)\nsearcher, _ := xdb.LoadContentFromFile(newPath) // mismatched sources\n// after\nheader, _ := xdb.LoadHeaderFromFile(path)\ncontent, _ := xdb.LoadContentFromFile(path) // same path/build","handlingStrategy":"validation","validationCode":"fi, _ := os.Stat(xdbPath)\nhdr, _ := xdb.LoadHeaderFromFile(xdbPath)\nif fi.Size() != int64(hdr.Length) {\n    return fmt.Errorf(\"xdb incomplete: on-disk %d, header says %d\", fi.Size(), hdr.Length)\n}","typeGuard":null,"tryCatchPattern":"region, err := searcher.Search(ctx, ip)\nif err != nil {\n    if strings.Contains(err.Error(), \"read region\") {\n        return \"\", fmt.Errorf(\"region data unreadable — xdb likely truncated: %w\", err)\n    }\n    return err\n}","preventionTips":["Verify size == header.Length before serving traffic with a new xdb.","Build header/content/file from a single source path.","Atomic-replace (rename) the xdb file on update, then recreate the searcher.","Monitor for this error as a signal of truncated deployments."],"tags":["golang","xdb","io-error","region-data"],"backgroundTag":"xdb-read-failed","analyzedSha":"c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1","analyzedAt":"2026-09-02T16:58:39.988Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}