{"record":{"id":"60d4021f345438a7","repo":"charmbracelet/crush","slug":"s-s-expects-a-number-got-q","errorCode":null,"errorMessage":"%s: --%s expects a number, got %q","messagePattern":"(.+?): --(.+?) expects a number, got %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/shellconfig/flags.go","lineNumber":145,"sourceCode":"\tcase flagInt:\n\t\tv, err := nextArg(args, i, name)\n\t\tif err != nil {\n\t\t\treturn nil, 0, err\n\t\t}\n\t\tn, err := strconv.ParseInt(v, 10, 64)\n\t\tif err != nil {\n\t\t\treturn nil, 0, fmt.Errorf(\"%s: --%s expects an integer, got %q\", args[0], name, v)\n\t\t}\n\t\treturn n, i + 2, nil\n\n\tcase flagFloat:\n\t\tv, err := nextArg(args, i, name)\n\t\tif err != nil {\n\t\t\treturn nil, 0, err\n\t\t}\n\t\tf, err := strconv.ParseFloat(v, 64)\n\t\tif err != nil {\n\t\t\treturn nil, 0, fmt.Errorf(\"%s: --%s expects a number, got %q\", args[0], name, v)\n\t\t}\n\t\treturn f, i + 2, nil\n\n\tcase flagKeyValue:\n\t\tif i+2 >= len(args) {\n\t\t\treturn nil, 0, fmt.Errorf(\"%s: --%s requires a key and value\", args[0], name)\n\t\t}\n\t\treturn [2]string{args[i+1], args[i+2]}, i + 3, nil\n\n\tcase flagJSONObject:\n\t\tv, err := nextArg(args, i, name)\n\t\tif err != nil {\n\t\t\treturn nil, 0, err\n\t\t}\n\t\tvar object map[string]any\n\t\tif err := json.Unmarshal([]byte(v), &object); err != nil || object == nil {\n\t\t\treturn nil, 0, fmt.Errorf(\"%s: --%s expects a JSON object, got %q\", args[0], name, v)\n\t\t}","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/shellconfig/flags.go#L127-L163","documentation":"parseFlagValue validates float flags via strconv.ParseFloat(v, 64). A value that isn't a valid number after a flagFloat flag causes applyFlags to fail with \"<cmd>: --<flag> expects a number, got %q\". Like the bool/int variants, this aborts crushrc config construction.","triggerScenarios":"A crushrc builtin call with e.g. `--temperature high` or `--threshold 0,75` where the flag was declared flagFloat; empty values or values with units (50%).","commonSituations":"Users writing percentages with %, decimal commas from non-English locales, or named values (high/low) for numeric tuning options like model temperature.","solutions":["Provide a plain decimal number using a dot as the decimal separator (e.g. 0.7).","Convert percentage/units notation to a plain number (50 not 50%).","Check the flag's declared type; if it's flagInt use an integer instead.","Quote-free plain values only — surrounding shell quoting can introduce stray characters."],"exampleFix":"// before (crushrc)\noptions --temperature 0,7\n// after\noptions --temperature 0.7","handlingStrategy":"validation","validationCode":"func isFloatLiteral(v string) bool {\n\t_, err := strconv.ParseFloat(v, 64)\n\treturn err == nil\n}","typeGuard":null,"tryCatchPattern":"err := cfg.Apply(args)\nif err != nil && strings.Contains(err.Error(), \"expects a number\") {\n\t// show cmd+flag and offending value from the message\n}","preventionTips":["Use dot as decimal separator (0.7), never locale commas.","Strip units and percent signs from numeric values.","Confirm the flag is flagFloat; use integers for flagInt flags.","Add automated validation of crushrc numeric options in CI."],"tags":["config","flags","validation"],"backgroundTag":"invalid-flag-value","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}