larksuite/cli · error

multiple plugins called Restrict; only one plugin may own th

Error message

multiple plugins called Restrict; only one plugin may own the policy

What it means

ErrMultipleRestricts indicates the platform policy resolver found more than one plugin calling Restrict() during initialization. The policy can only have a single owning plugin; when distinctOwners(PluginRules) yields more than one owner, Resolve fails with this sentinel plus the conflicting owner names. It exists so the failure is explicit and classifiable (ReasonMultipleRestricts) rather than an ambiguous precedence decision.

Source

Thrown at internal/cmdpolicy/resolver.go:40

)

type ResolveSource struct {
	Kind SourceKind
	Name string
}

type PluginRule struct {
	PluginName string
	Rule       *platform.Rule
}

type Sources struct {
	PluginRules []PluginRule
	YAMLRules   []*platform.Rule
	YAMLPath    string
}

var ErrMultipleRestricts = errors.New("multiple plugins called Restrict; only one plugin may own the policy")

// Resolve picks by precedence: plugin > yaml > none, returning the full
// rule set the winning source contributes. Pure function; load yaml via
// LoadYAMLPolicy first. Every returned rule is validated.
//
// Multi-rule semantics (single owner): one plugin may contribute several
// rules (each a scoped grant, OR-combined by the engine), but two or more
// DISTINCT plugins contributing rules is still a configuration error --
// the resolver aborts so independent plugins cannot silently widen each
// other's policy. yaml may likewise carry several rules under "rules:".
func Resolve(s Sources) ([]*platform.Rule, ResolveSource, error) {
	owners := distinctOwners(s.PluginRules)
	if len(owners) > 1 {
		return nil, ResolveSource{}, fmt.Errorf("%w: %v", ErrMultipleRestricts, owners)
	}

	if len(s.PluginRules) > 0 {
		rules := make([]*platform.Rule, 0, len(s.PluginRules))

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Remove or disable one of the plugins calling Restrict so exactly one owns the policy
  2. Consolidate both rule sets into a single restricting plugin
  3. Check the plugin list/config for accidentally duplicated policy plugins

Example fix

// before
plugins := []Plugin{readonlyPlugin, companyPolicyPlugin} // both call Restrict
// after
plugins := []Plugin{companyPolicyPlugin} // single policy owner
Defensive patterns

Strategy: validation

Validate before calling

owners := distinctOwners(pluginRules)
if len(owners) > 1 {
    return fmt.Errorf("multiple policy plugins: %v", owners)
}

Type guard

func isMultipleRestricts(err error) bool { return errors.Is(err, cmdpolicy.ErrMultipleRestricts) }

Try / catch

policy, err := cmdpolicy.Resolve(sources)
if errors.Is(err, cmdpolicy.ErrMultipleRestricts) {
    // inspect err text for owner list, disable one plugin
}

Prevention

When it happens

Trigger: Loading a plugin set where two or more plugins each call cmdpolicy Restrict(); calling Resolve (or the platform guard wiring in cmd/platform_guards.go) with such a rule list.

Common situations: Installing two policy-restricting plugins (e.g. a readonly plugin plus a custom company policy plugin) that both try to own the guard policy; misconfigured plugin manifest enabling a second restrictor unintentionally.

Related errors


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