{"record":{"id":"690869443b472f03","repo":"crowdsecurity/crowdsec","slug":"long1-is-not-a-float-v","errorCode":null,"errorMessage":"long1 is not a float : %v","messagePattern":"long1 is not a float : (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/exprhelpers/helpers.go","lineNumber":402,"sourceCode":"// func Distance(lat1 string, long1 string, lat2 string, long2 string) (float64, error) {\nfunc Distance(params ...any) (any, error) {\n\tlat1 := params[0].(string)\n\tlong1 := params[1].(string)\n\tlat2 := params[2].(string)\n\tlong2 := params[3].(string)\n\n\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) {","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/exprhelpers/helpers.go#L384-L420","documentation":"The Distance expr helper parses all four coordinate arguments as float64 strings. This error is thrown when the long1 (first longitude) argument cannot be parsed by strconv.ParseFloat; the helper logs a warning and returns (0.0, error).","triggerScenarios":"Calling exprhelpers.Distance where long1 is non-numeric — empty string, \"2.3522E\" (truncated exponent), \"2,3522\", or a field holding a placeholder like \"unknown\".","commonSituations":"GeoIP enrichment that produced empty or sentinel longitude values; CSV-sourced numbers with comma decimals; fields concatenated with units (\"2.3522°\").","solutions":["Pass long1 as a plain decimal string such as \"2.3522\".","Normalize/cleanse the longitude field in the parser (strip symbols, convert commas) before Distance is evaluated.","Add a numeric precondition in the expression so Distance is only called with valid coordinates.","Check that the GeoIP enrichment actually ran and populated the field; empty strings always fail ParseFloat."],"exampleFix":"// before\nDistance(lat, \"2.3522°\", lat2, long2)\n// after\nDistance(lat, \"2.3522\", lat2, long2)","handlingStrategy":"validation","validationCode":"if _, err := strconv.ParseFloat(long1, 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: use isNumeric(long1) in the condition guarding the Distance call; treat its error return as 'unknown distance', not 0","preventionTips":["Strip degree symbols and direction letters from longitude fields during parsing","Verify GeoIP enrichment output for the source IP before geo distance checks","Cover geo parsing with unit tests using real log samples"],"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"}