larksuite/cli · error
%s must be an integer
Error message
%s must be an integer
What it means
A field typed as integer received a JSON number that is not an integer — typically a float like 3.5, or a JSON number decoded as float64 without integral value. validationInteger(value) rejects it before constraint checks. Note: an integral float such as 3.0 may also be rejected depending on validationInteger, since JSON decoding yields float64.
Source
Thrown at shortcuts/common/typed_binder.go:441
return fmt.Errorf("%s must contain at most %d characters", path, *constraint.MaxLength)
}
if len(constraint.Enum) > 0 && !slices.Contains(constraint.Enum, text) {
return fmt.Errorf("%s must be one of: %s", path, strings.Join(constraint.Enum, ", "))
}
return nil
case typedBooleanShape:
boolean, ok := value.(bool)
if !ok {
return fmt.Errorf("%s must be a boolean", path)
}
if len(constraint.Enum) > 0 && !slices.Contains(constraint.Enum, boolean) {
return fmt.Errorf("%s has an unsupported boolean value", path)
}
return nil
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)View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Round or floor the value to a whole number before passing it
- If the source is a string, convert it to an integer (and keep it unquoted in JSON)
- Check `schema` for the field's type; use the number-typed field if fractions are intended
- Beware float64 artifacts: compute with integers where possible
Example fix
// before
size := total / 2 // 2.5 on odd totals
// after
size := total / 2
if total%2 != 0 { size = (total+1)/2 } // keep it integral
// or: size := int(math.Ceil(float64(total)/2)) Defensive patterns
Strategy: validation
Validate before calling
func ensureIntegral(v any) error {
switch n := v.(type) {
case int, int64:
return nil
case float64:
if n != math.Trunc(n) {
return fmt.Errorf("%v is not an integer", n)
}
return nil
default:
return fmt.Errorf("expected integer, got %T", v)
}
} Type guard
func isIntegral(v any) bool {
n, ok := v.(float64)
return ok && n == math.Trunc(n)
} Try / catch
if err := bind(field, v); err != nil {
if strings.Contains(err.Error(), "must be an integer") {
return fmt.Errorf("field %s needs a whole number; got %v: %w", field, v, err)
}
return err
} Prevention
- Use int/int64 Go fields for integer-typed schema fields
- Round or ceil computed values explicitly before binding
- Keep numbers unquoted in JSON and convert string sources with strconv.Atoi
- Beware float division producing fractions; use integer math where possible
When it happens
Trigger: Passing 1.5 to an integer field; supplying a computed value like size/2 that yields a fractional number; passing a numeric string "42" (not a number at all) validated through validateCompiledValue.
Common situations: Doing arithmetic in shell/scripts that produces decimals; copying float values from other APIs (page sizes, durations in seconds); YAML/JSON configs where IDs were quoted or written with decimals.
Related errors
- %s must be a boolean
- %s must be a number
- %s must be an array
- %s must be an object
- %s must be at least %d
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/3acde85d9a0449c0.
Report an issue: GitHub.