{"record":{"id":"3d5c201d5fbb61b7","repo":"crowdsecurity/crowdsec","slug":"lat2-is-not-a-float-v","errorCode":null,"errorMessage":"lat2 is not a float : %v","messagePattern":"lat2 is not a float : (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/exprhelpers/helpers.go","lineNumber":409,"sourceCode":"\tlat1f, err := strconv.ParseFloat(lat1, 64)\n\tif err != nil {\n\t\tlog.Warningf(\"lat1 is not a float : %v\", err)\n\n\t\treturn 0.0, fmt.Errorf(\"lat1 is not a float : %v\", err)\n\t}\n\n\tlong1f, err := strconv.ParseFloat(long1, 64)\n\tif err != nil {\n\t\tlog.Warningf(\"long1 is not a float : %v\", err)\n\n\t\treturn 0.0, fmt.Errorf(\"long1 is not a float : %v\", err)\n\t}\n\n\tlat2f, err := strconv.ParseFloat(lat2, 64)\n\tif err != nil {\n\t\tlog.Warningf(\"lat2 is not a float : %v\", err)\n\n\t\treturn 0.0, fmt.Errorf(\"lat2 is not a float : %v\", err)\n\t}\n\n\tlong2f, err := strconv.ParseFloat(long2, 64)\n\tif err != nil {\n\t\tlog.Warningf(\"long2 is not a float : %v\", err)\n\n\t\treturn 0.0, fmt.Errorf(\"long2 is not a float : %v\", err)\n\t}\n\n\t// either set of coordinates is 0,0, return 0 to avoid FPs\n\tif (lat1f == 0.0 && long1f == 0.0) || (lat2f == 0.0 && long2f == 0.0) {\n\t\tlog.Warningf(\"one of the coordinates is 0,0, returning 0\")\n\t\treturn 0.0, nil\n\t}\n\n\tfirst := haversine.Coord{Lat: lat1f, Lon: long1f}\n\tsecond := haversine.Coord{Lat: lat2f, Lon: long2f}\n","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/exprhelpers/helpers.go#L391-L427","documentation":"The Distance expr helper parses lat2 with strconv.ParseFloat as its third coordinate conversion. This error is thrown when the lat2 argument is not a valid float string; the helper logs a warning and returns (0.0, error).","triggerScenarios":"Calling exprhelpers.Distance where lat2 is non-numeric — missing enrichment field (\"\"), scientific-notation garbage, or a string with spaces (\" 48.8566\").","commonSituations":"Second event's geolocation missing because its IP had no GeoIP data; whitespace or BOM characters in fields extracted from logs; parsing a hex or other non-decimal representation.","solutions":["Ensure lat2 is a clean decimal string like \"51.5074\" before calling Distance.","Trim whitespace/BOM and validate numeric format in the parser stage.","Skip the Distance call in the expression when the reference event lacks geolocation enrichment.","Note ParseFloat accepts forms like \"1e2\" and \"Inf\" — validate against a strict decimal pattern if that's unwanted."],"exampleFix":"// before\nDistance(lat1, long1, evt.Enriched.geo.latitude, long2) // empty when enrichment missing\n// after\nlat2 != \"\" && Distance(lat1, long1, lat2, long2) > 100","handlingStrategy":"validation","validationCode":"if _, err := strconv.ParseFloat(lat2, 64); err != nil {\n\t// skip Distance call\n}","typeGuard":"func isFloat(s string) bool {\n\t_, err := strconv.ParseFloat(s, 64)\n\treturn err == nil\n}","tryCatchPattern":"expr: require lat2 != \"\" (and isNumeric(lat2)) before Distance; fall back to an explicit 'no-data' branch rather than 0.0","preventionTips":["Trim whitespace/BOM from extracted fields before numeric conversion","Skip geo-distance logic when the reference event has no geolocation","Remember ParseFloat accepts \"1e2\"/\"Inf\" — use a strict decimal regex if that matters"],"tags":["geo","parsing","expr","crowdsec"],"backgroundTag":"invalid-argument-format","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}