larksuite/cli · error
%s got both %q and "range" — keep "range" and drop %q
Error message
%s got both %q and "range" — keep "range" and drop %q
What it means
Special case for the ranges/range pair: when the vocab has `range` but not `ranges`, a `ranges` key in the input conflicts with an existing `range` key. The dispatcher errors, telling you to keep `range` and drop the `ranges` spelling.
Source
Thrown at shortcuts/sheets/batch_op_dispatch.go:494
// before its target ("size" < "width"), so nothing has claimed the
// logical key yet. Name both spellings and the survivor.
taken := target
if underscoreTaken {
taken = underscored
}
if jsonEqual(input[k], input[taken]) {
delete(input, k) // same value under two names: drop the alias.
// Hand the logical key over to the surviving spelling, or the
// claim recorded above would still point at the deleted alias
// and make that spelling's own turn read as a conflict.
canonical[target] = taken
continue
}
return fmt.Errorf("%s got both %q and %q, which are two names for the same flag, with different values — keep %q", sc, k, taken, taken) //nolint:forbidigo // intermediate error; the batch dispatcher wraps it into a typed operations validation error
}
if strings.ToLower(hv) == "ranges" && vocab["range"] && !vocab["ranges"] {
if _, taken := input["range"]; taken {
return fmt.Errorf("%s got both %q and \"range\" — keep \"range\" and drop %q", sc, k, k) //nolint:forbidigo // intermediate error; the batch dispatcher wraps it into a typed operations validation error
}
if arr, isArr := input[k].([]interface{}); isArr {
if len(arr) == 1 {
if s, isStr := arr[0].(string); isStr {
input["range"] = s
delete(input, k)
continue
}
}
return fmt.Errorf("%s takes a single \"range\" per sub-op, got %d entries in %q — split them into %d sub-ops (one per range)", sc, len(arr), k, len(arr)) //nolint:forbidigo // intermediate error; the batch dispatcher wraps it into a typed operations validation error
}
if s, isStr := input[k].(string); isStr {
input["range"] = s
delete(input, k)
continue
}
}
msg := fmt.Sprintf("unknown input key %q", k)View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Remove the `ranges` key and keep the `range` key.
- If you meant multiple ranges, split them into multiple sub-ops, one per range, each with a single `range`.
- Update legacy payloads that used the plural key to the singular form.
Example fix
// before
{"range": "Sheet1!A1:B2", "ranges": ["Sheet1!C1:D2"]}
// after
{"range": "Sheet1!A1:B2"} // plus a second sub-op for Sheet1!C1:D2 Defensive patterns
Strategy: validation
Validate before calling
if r, ok := op["ranges"]; ok {
if _, also := op["range"]; also {
return errors.New("use only `range` (single value) or split into sub-ops")
}
_ = r
} Prevention
- Use `range` (singular) for ops whose schema declares only `range`.
- For multi-range writes, emit one sub-op per range.
- Migrate any payload templates that still use the plural `ranges` key.
When it happens
Trigger: Sub-op input contains both `range` and `ranges` (in any casing normalized to `ranges`) for an op whose vocabulary only accepts a single `range` field.
Common situations: Reusing payload shapes from ops that accept `ranges` in ops that take one `range`; older scripts written against a plural-key API version.
Related errors
- %s got conflicting values for %q under two spellings (%q and
- %s got both %q and %q — keep %q and drop the other
- %s got both %q and %q, which are two names for the same flag
- Range needs a maximum column: {range_ref}
- Range needs a maximum row: {range_ref}
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/16b3e49a70a9a999.
Report an issue: GitHub.