{"record":{"id":"cc78fed100201c52","repo":"lionsoul2014/ip2region","slug":"ipsub-s-s-w","errorCode":null,"errorMessage":"IPSub(%s, %s): %w","messagePattern":"IPSub\\((.+?), (.+?)\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"binding/golang/xdb/util.go","lineNumber":132,"sourceCode":"\tvar carry byte = 0\n\n\tfor i := 0; i < length; i++ {\n\t\t// 1. Shift current byte right by 1\n\t\t// 2. Or (|) with the carry from the previous byte (shifted to the MSB position)\n\t\tresult[i] = (ip[i] >> 1) | (carry << 7)\n\n\t\t// 3. Capture the Least Significant Bit (LSB) to use as carry for the next byte\n\t\tcarry = ip[i] & 1\n\t}\n\n\treturn result\n}\n\n// IPMiddle get the middle value of two input ip address\nfunc IPMiddle(sip, eip []byte) ([]byte, error) {\n\tbuf, err := IPAdd(sip, eip)\n\tif err != nil {\n\t\treturn []byte{}, fmt.Errorf(\"IPSub(%s, %s): %w\", IP2String(sip), IP2String(eip), err)\n\t}\n\n\treturn IPHalf(buf), nil\n}\n\n// Verify if the current Searcher could be used to search the specified xdb file.\n// Why do we need this check ?\n// The future features of the xdb impl may cause the current searcher not able to work properly.\n//\n// @Note: You Just need to check this ONCE when the service starts\n// Or use another process (eg, A command) to check once Just to confirm the suitability.\nfunc Verify(handle *os.File) error {\n\theader, err := LoadHeader(handle)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"loading header: %w\", err)\n\t}\n\n\t// get the runtime ptr bytes","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/lionsoul2014/ip2region/blob/c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1/binding/golang/xdb/util.go#L114-L150","documentation":"IPMiddle computes the midpoint of two IPs and calls IPAdd internally; if IPAdd fails (e.g. length mismatch), the error is wrapped as IPSub(%s, %s): %w with both IPs stringified. Note the message says IPSub but the failing call is IPAdd — the wrap is mislabeled.","triggerScenarios":"Calling IPMiddle with a 4-byte and a 16-byte IP; passing empty slices (length 0 vs 0 passes, but 0 vs non-0 fails); calling with IPs from different address families.","commonSituations":"Splitting IP ranges from a data file that contains both v4 and v6 segments; refactoring code that changed one operand to To16 but not the other; unit tests feeding heterogeneous slices.","solutions":["Make both inputs the same byte length (both To4 or both To16) before calling IPMiddle","Read the wrapped %w error — it will be \"length of the two ips are not the same\" from IPAdd","Ensure the sip <= eip pair belongs to the same IP version in your range data","Ignore the misleading IPSub prefix; it is a known labeling quirk in this code path"],"exampleFix":"// before\nm, err := xdb.IPMiddle(sip4, eip6) // IPSub(...): length of the two ips are not the same\n// after\nif len(sip4) != len(eip6) { return errors.New(\"range spans v4/v6\") }\nmid, err := xdb.IPMiddle(net.IP(sip4).To16(), net.IP(eip6).To16())","handlingStrategy":"type-guard","validationCode":"func canIPMiddle(sip, eip []byte) bool {\n    return len(sip) == len(eip) && len(sip) > 0\n}","typeGuard":"func isSameFamily(sip, eip []byte) bool {\n    return len(sip) > 0 && len(sip) == len(eip)\n}","tryCatchPattern":"mid, err := xdb.IPMiddle(sip, eip)\nif err != nil {\n    // note: wrapped error mentions IPSub but originates from IPAdd\n    return fmt.Errorf(\"ip middle (%d/%d bytes): %w\", len(sip), len(eip), err)\n}","preventionTips":["Ensure both operands use the same encoding width before calling IPMiddle","Remember the IPSub prefix in the message is a mislabel; inspect the wrapped %w cause","Only call IPMiddle within a single IP-version range"],"tags":["go","ip-address","misleading-message"],"backgroundTag":"ip-length-mismatch","analyzedSha":"c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1","analyzedAt":"2026-09-02T16:58:39.988Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}