{"record":{"id":"c9845daf3e7c7d06","repo":"lionsoul2014/ip2region","slug":"incomplete-read-readed-bytes-should-be-d","errorCode":null,"errorMessage":"incomplete read: readed bytes should be %d","messagePattern":"incomplete read: readed bytes should be (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"binding/golang/xdb/searcher.go","lineNumber":211,"sourceCode":"\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)\n\t\t}\n\n\t\ts.ioCount++\n\t\trLen, err := s.dbReader.Read(buff)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"handle read: %w\", err)\n\t\t}\n\n\t\tif rLen != len(buff) {\n\t\t\treturn fmt.Errorf(\"incomplete read: readed bytes should be %d\", len(buff))\n\t\t}\n\t}\n","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/lionsoul2014/ip2region/blob/c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1/binding/golang/xdb/searcher.go#L193-L229","documentation":"read() copies from the in-memory content buffer when available; if copy() moved fewer bytes than the requested buffer length, the offset range extends past the content buffer and this error is returned naming the expected byte count.","triggerScenarios":"Any Search/read at an offset beyond len(contentBuff): content buffer smaller than the real xdb (truncated file passed to LoadContentFromBuff), or a corrupted index pointing past the buffer end.","commonSituations":"Truncated download; loading a v4 header with a v6 content buffer (or vice versa); reading an xdb whose contentBuff was sliced/trimmed by the caller.","solutions":["Verify len(contentBuff) equals the full xdb file size before creating the searcher.","Re-download/regenerate the xdb; it is truncated.","Ensure header and content buffer are from the same file build.","Validate offsets: header.Length should be <= len(contentBuff)."],"exampleFix":"// before\nbuff, _ := os.ReadFile(path)\nsearcher, _ := xdb.NewSearcher(header, buff) // buff truncated upstream\n// after\nbuff, err := os.ReadFile(path)\nif err != nil { return err }\nif len(buff) < header.Length {\n    return fmt.Errorf(\"xdb content too small: %d < %d\", len(buff), header.Length)\n}\nsearcher, err := xdb.NewSearcher(header, buff)","handlingStrategy":"validation","validationCode":"if len(contentBuff) < header.Length {\n    return fmt.Errorf(\"content buffer %d bytes < header length %d\", len(contentBuff), header.Length)\n}","typeGuard":"func sufficientContent(h *xdb.Header, buff []byte) bool { return len(buff) >= h.Length }","tryCatchPattern":"region, err := searcher.Search(ctx, ip)\nif err != nil && strings.Contains(err.Error(), \"incomplete read\") {\n    return \"\", fmt.Errorf(\"xdb content buffer truncated — reload full file: %w\", err)\n}","preventionTips":["Always pass the complete file bytes to content-buffer searchers.","Check len(buff) against header.Length at load time.","Avoid copying content buffers with slicing that could drop the tail.","Regenerate/re-download the xdb if sizes disagree."],"tags":["golang","xdb","incomplete-read","content-buffer"],"backgroundTag":"incomplete-read","analyzedSha":"c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1","analyzedAt":"2026-09-02T16:58:39.988Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}