{"record":{"id":"f90176fe6024bd8e","repo":"larksuite/cli","slug":"s-must-be-a-number","errorCode":null,"errorMessage":"%s must be a number","messagePattern":"(.+?) must be a number","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/common/typed_binder.go","lineNumber":456,"sourceCode":"\tcase typedIntegerShape:\n\t\tnumber, ok := validationInteger(value)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"%s must be an integer\", path)\n\t\t}\n\t\tif constraint.Minimum != nil && number < *constraint.Minimum {\n\t\t\treturn fmt.Errorf(\"%s must be at least %d\", path, *constraint.Minimum)\n\t\t}\n\t\tif constraint.Maximum != nil && number > *constraint.Maximum {\n\t\t\treturn fmt.Errorf(\"%s must be at most %d\", path, *constraint.Maximum)\n\t\t}\n\t\tif len(constraint.Enum) > 0 && !slices.Contains(constraint.Enum, number) {\n\t\t\treturn fmt.Errorf(\"%s has an unsupported integer value\", path)\n\t\t}\n\t\treturn nil\n\tcase typedNumberShape:\n\t\tnumber, ok := validationNumber(value)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"%s must be a number\", path)\n\t\t}\n\t\tif len(constraint.Enum) > 0 && !slices.Contains(constraint.Enum, number) {\n\t\t\treturn fmt.Errorf(\"%s has an unsupported number value\", path)\n\t\t}\n\t\tif constraint.Minimum != nil && number < *constraint.Minimum {\n\t\t\treturn fmt.Errorf(\"%s must be at least %v\", path, *constraint.Minimum)\n\t\t}\n\t\tif constraint.Maximum != nil && number > *constraint.Maximum {\n\t\t\treturn fmt.Errorf(\"%s must be at most %v\", path, *constraint.Maximum)\n\t\t}\n\t\treturn nil\n\tcase typedArrayShape:\n\t\titems, ok := value.([]any)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"%s must be an array\", path)\n\t\t}\n\t\tif constraint.MinItems != nil && len(items) < *constraint.MinItems {\n\t\t\treturn fmt.Errorf(\"%s must contain at least %d items\", path, *constraint.MinItems)","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/common/typed_binder.go#L438-L474","documentation":"A field typed as number (float allowed) received a value that is not a JSON number at all — commonly a numeric string \"3.14\", a bool, or null. validationNumber(value) fails the type assertion. JSON type fidelity matters: quoted numbers are strings.","triggerScenarios":"Passing \"1.5\" (quoted) to a number field; shell variable interpolation quoting the value; passing null to a required number in a nested object validated by valueCompatibleWithShape.","commonSituations":"Reading values from env vars or CLI text input (always strings) without conversion; config files where the number was quoted; hand-built JSON templates that quote numeric fields.","solutions":["Convert string input with strconv.ParseFloat before binding","Remove quotes around numeric literals in JSON/templates","For env/config sources, parse explicitly: v, err := strconv.ParseFloat(os.Getenv(\"RATIO\"), 64)","Confirm the field type via `schema`; if it is integer-typed, supply an integer instead"],"exampleFix":"// before\nratio := os.Getenv(\"RATIO\")          // \"1.5\" (string)\nbody := map[string]any{\"ratio\": ratio}\n// after\nratio, err := strconv.ParseFloat(os.Getenv(\"RATIO\"), 64)\nif err != nil { return err }\nbody := map[string]any{\"ratio\": ratio}","handlingStrategy":"type-guard","validationCode":"func ensureNumber(v any) error {\n    switch v.(type) {\n    case float64, float32, int, int64:\n        return nil\n    default:\n        return fmt.Errorf(\"expected JSON number, got %T\", v)\n    }\n} // convert string sources first: strconv.ParseFloat","typeGuard":"func isJSONNumber(v any) bool {\n    switch v.(type) {\n    case float64, float32, int, int64:\n        return true\n    }\n    return false\n}","tryCatchPattern":"if err := bind(field, v); err != nil {\n    if strings.Contains(err.Error(), \"must be a number\") {\n        return fmt.Errorf(\"field %s needs an unquoted JSON number: %w\", field, err)\n    }\n    return err\n}","preventionTips":["Parse env/config strings with strconv.ParseFloat before binding","Use typed structs with float/int fields instead of map[string]any","Never quote numeric literals in hand-built JSON","Distinguish number vs integer fields via `schema` and supply the matching type"],"tags":["validation","cli","json","type-mismatch","number"],"backgroundTag":"schema-type-mismatch","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}