larksuite/cli · error

value is incompatible with %s: %w

Error message

value is incompatible with %s: %w

What it means

valueAssignableTo round-trips the default value through JSON (Marshal then Unmarshal into a reflect.New(target)) to prove it is compatible with the declared target type. If Unmarshal fails, this error wraps the JSON error with the target type name, indicating the default's shape does not fit the field's Go type.

Source

Thrown at shortcuts/common/typed_compile_args.go:641

	if base.Kind() == reflect.Array && value != nil {
		source := reflect.ValueOf(value)
		for source.Kind() == reflect.Pointer || source.Kind() == reflect.Interface {
			if source.IsNil() {
				break
			}
			source = source.Elem()
		}
		if (source.Kind() == reflect.Array || source.Kind() == reflect.Slice) && source.Len() != base.Len() {
			return fmt.Errorf("array default for %s requires exactly %d items, got %d", target, base.Len(), source.Len())
		}
	}
	encoded, err := json.Marshal(value)
	if err != nil {
		return err
	}
	decoded := reflect.New(target)
	if err := json.Unmarshal(encoded, decoded.Interface()); err != nil {
		return fmt.Errorf("value is incompatible with %s: %w", target, err)
	}
	return nil
}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Align the default value with the field's Go type (e.g. numeric default for int fields, array for slices)
  2. Check the wrapped json error (%w cause) for the exact offset/type mismatch
  3. If the field uses a named type, ensure its JSON unmarshal accepts the default

Example fix

// before
type in struct{ Count int `cli:"default=many"` }
// after
type in struct{ Count int `cli:"default=3"` }
Defensive patterns

Strategy: type-guard

Validate before calling

func defaultAssignable(value any, target reflect.Type) error {
	encoded, err := json.Marshal(value)
	if err != nil { return err }
	return json.Unmarshal(encoded, reflect.New(target).Interface())
}

Type guard

func canUnmarshalAs(value any, target reflect.Type) bool {
	encoded, err := json.Marshal(value)
	if err != nil { return false }
	return json.Unmarshal(encoded, reflect.New(target).Interface()) == nil
}

Try / catch

if err := valueAssignableTo(def, fieldType); err != nil {
	var jsonErr *json.UnmarshalTypeError
	if errors.As(err, &jsonErr) { log.Fatalf("default %v does not fit %s at %s", def, jsonErr.Type, jsonErr.Field) }
	return err
}

Prevention

When it happens

Trigger: Assigning a default like a string to an int field, an object to a scalar, or a value that cannot unmarshal into a named type with a custom UnmarshalJSON rejecting it.

Common situations: Type drift after refactoring a field's type without updating its default; defaults written as untyped JSON strings/numbers that do not fit the declared Go type.

Related errors


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