{"record":{"id":"d03504ed5f0bb3aa","repo":"charmbracelet/crush","slug":"s-s-expects-an-integer-got-q","errorCode":null,"errorMessage":"%s: --%s expects an integer, got %q","messagePattern":"(.+?): --(.+?) expects an integer, got %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/shellconfig/flags.go","lineNumber":134,"sourceCode":"\tcase flagBool:\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\tb, err := parseBool(v)\n\t\tif err != nil {\n\t\t\treturn nil, 0, fmt.Errorf(\"%s: --%s expects true/false, got %q\", args[0], name, v)\n\t\t}\n\t\treturn b, i + 2, nil\n\n\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}","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/shellconfig/flags.go#L116-L152","documentation":"parseFlagValue validates integer flags via strconv.ParseInt(v, 10, 64). If the value following a flagInt flag isn't a base-10 integer, applyFlags aborts with \"<cmd>: --<flag> expects an integer, got %q\". This surfaces during crushrc config parsing, before any config is applied.","triggerScenarios":"A crushrc line like `options --timeout 30s` or `--retries three` where the flag was registered as flagInt; passing a float like 1.5 to an integer flag; hex (0x1F) or underscore-formatted numbers that ParseInt(…,10,64) rejects.","commonSituations":"Users writing durations with units (30s, 5m) for flags that expect plain integers; locale-formatted numbers (1,000); copy-pasted values with trailing whitespace or units.","solutions":["Provide a plain base-10 integer (e.g. 30000 instead of 30s).","Remove commas, units, or 0x prefixes from the value.","Trim whitespace/quotes around the value in the crushrc line.","If the flag truly needs a duration or float, the builtin author should declare it flagFloat or a string flag and parse it in the handler."],"exampleFix":"// before (crushrc)\noptions --timeout 30s\n// after\noptions --timeout 30","handlingStrategy":"validation","validationCode":"func isIntLiteral(v string) bool {\n\t_, err := strconv.ParseInt(v, 10, 64)\n\treturn err == nil\n}","typeGuard":null,"tryCatchPattern":"err := cfg.Apply(args)\nif err != nil && strings.Contains(err.Error(), \"expects an integer\") {\n\t// show cmd+flag and the offending value from the message\n}","preventionTips":["Write plain base-10 integers; convert durations (30s -> 30000) and drop units.","No commas, spaces, 0x prefixes, or underscores in integer flag values.","Consult the flag's declared type before writing its value.","Validate crushrc files with a quick parser test before committing."],"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"}