larksuite/cli · error
%s must be a number
Error message
%s must be a number
What it means
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.
Source
Thrown at shortcuts/common/typed_binder.go:456
case typedIntegerShape:
number, ok := validationInteger(value)
if !ok {
return fmt.Errorf("%s must be an integer", path)
}
if constraint.Minimum != nil && number < *constraint.Minimum {
return fmt.Errorf("%s must be at least %d", path, *constraint.Minimum)
}
if constraint.Maximum != nil && number > *constraint.Maximum {
return fmt.Errorf("%s must be at most %d", path, *constraint.Maximum)
}
if len(constraint.Enum) > 0 && !slices.Contains(constraint.Enum, number) {
return fmt.Errorf("%s has an unsupported integer value", path)
}
return nil
case typedNumberShape:
number, ok := validationNumber(value)
if !ok {
return fmt.Errorf("%s must be a number", path)
}
if len(constraint.Enum) > 0 && !slices.Contains(constraint.Enum, number) {
return fmt.Errorf("%s has an unsupported number value", path)
}
if constraint.Minimum != nil && number < *constraint.Minimum {
return fmt.Errorf("%s must be at least %v", path, *constraint.Minimum)
}
if constraint.Maximum != nil && number > *constraint.Maximum {
return fmt.Errorf("%s must be at most %v", path, *constraint.Maximum)
}
return nil
case typedArrayShape:
items, ok := value.([]any)
if !ok {
return fmt.Errorf("%s must be an array", path)
}
if constraint.MinItems != nil && len(items) < *constraint.MinItems {
return fmt.Errorf("%s must contain at least %d items", path, *constraint.MinItems)View on GitHub (pinned to 7fd6ef3c07)
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
Example fix
// before
ratio := os.Getenv("RATIO") // "1.5" (string)
body := map[string]any{"ratio": ratio}
// after
ratio, err := strconv.ParseFloat(os.Getenv("RATIO"), 64)
if err != nil { return err }
body := map[string]any{"ratio": ratio} Defensive patterns
Strategy: type-guard
Validate before calling
func ensureNumber(v any) error {
switch v.(type) {
case float64, float32, int, int64:
return nil
default:
return fmt.Errorf("expected JSON number, got %T", v)
}
} // convert string sources first: strconv.ParseFloat Type guard
func isJSONNumber(v any) bool {
switch v.(type) {
case float64, float32, int, int64:
return true
}
return false
} Try / catch
if err := bind(field, v); err != nil {
if strings.Contains(err.Error(), "must be a number") {
return fmt.Errorf("field %s needs an unquoted JSON number: %w", field, err)
}
return err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- %s must be a boolean
- %s must be an integer
- %s must be an array
- %s must be an object
- %s has an unsupported number value
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/f90176fe6024bd8e.
Report an issue: GitHub.