larksuite/cli · error

%s must be an object

Error message

%s must be an object

What it means

Object shape validation: a field declared as a typed object received a value that is not a JSON object after decoding. The type assertion to map[string]any fails and the binder reports the field path.

Source

Thrown at shortcuts/common/typed_binder.go:488

		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)
		}
		if constraint.MaxItems != nil && len(items) > *constraint.MaxItems {
			return fmt.Errorf("%s must contain at most %d items", path, *constraint.MaxItems)
		}
		for i, item := range items {
			if err := validateJSONValueAgainstShape(item, constraint.Items, fmt.Sprintf("%s[%d]", path, i)); err != nil {
				return err
			}
		}
		return nil
	case typedObjectShape:
		object, ok := value.(map[string]any)
		if !ok {
			return fmt.Errorf("%s must be an object", path)
		}
		fields := make(map[string]typedValueField, len(constraint.Fields))
		for _, field := range constraint.Fields {
			fields[field.Name] = field
			if field.Required {
				if _, exists := object[field.Name]; !exists {
					return fmt.Errorf("%s.%s is required", path, field.Name)
				}
			}
		}
		for name, item := range object {
			field, exists := fields[name]
			if !exists {
				if !constraint.AdditionalProperties {
					return fmt.Errorf("%s contains unknown field %q", path, name)
				}
				if constraint.AdditionalPropertiesShape != nil {
					if err := validateJSONValueAgainstShape(item, constraint.AdditionalPropertiesShape, path+"."+name); err != nil {

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Wrap the value as a JSON object with braces and quoted keys.
  2. Verify with --help/schema that the field is an object and inspect its declared fields.
  3. Quote the whole argument to survive shell brace expansion.
  4. Validate the JSON with a parser (jq) before passing it.

Example fix

// before
lark-cli shortcut demo --settings 'key=value'
// error: settings must be an object

// after
lark-cli shortcut demo --settings '{"key":"value"}'
Defensive patterns

Strategy: type-guard

Validate before calling

value='{"a":1}'
echo "$value" | jq -e 'type=="object"' >/dev/null || { echo "expected a JSON object" >&2; exit 2; }

Type guard

func isJSONObject(raw string) bool {
    var v map[string]any
    return json.Unmarshal([]byte(raw), &v) == nil
}

Try / catch

err := cmd.Run()
var valErr *errs.ValidationError
if errors.As(err, &valErr) && strings.Contains(valErr.Error(), "must be an object") {
    // fix the payload to a JSON object and retry
}

Prevention

When it happens

Trigger: Passing a scalar or array where a JSON object flag is expected — e.g. --settings 'foo' or --settings '[1,2]' instead of '{"key":"value"}'.

Common situations: Shell quoting mangling braces; forgetting the outer {} around key/value payloads; config files storing a stringified object without parsing; nesting mistakes (object expected, array of objects given).

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/80aebe4b71f75dae. Report an issue: GitHub.