larksuite/cli · error
Restrict(nil): rule must not be nil
Error message
Restrict(nil): rule must not be nil
What it means
The Builder's Restrict() method was called with a nil *Rule. The builder collects errors into b.errs instead of panicking so chained construction can report all problems at Build() time. A nil rule cannot express any capability restriction, so the call is rejected.
Source
Thrown at extension/platform/builder.go:138
if !b.validateHookName(hookName, "on") {
return b
}
e, n, f := event, hookName, fn
b.actions = append(b.actions, func(r Registrar) {
r.On(e, n, f)
})
return b
}
// Restrict contributes a pruning Rule. Calling Restrict implicitly
// sets Restricts=true and FailurePolicy=FailClosed (the framework
// requires both to coexist; the builder enforces the pairing so the
// plugin author cannot accidentally ship a policy plugin under
// FailOpen). It may be called more than once; each call adds one scoped
// Rule and the engine OR-combines them.
func (b *Builder) Restrict(rule *Rule) *Builder {
if rule == nil {
b.errs = append(b.errs, errors.New("Restrict(nil): rule must not be nil"))
return b
}
b.caps.Restricts = true
b.caps.FailurePolicy = FailClosed
// Defensive clone: capture an independent snapshot so a caller that
// reuses and mutates the same *Rule across multiple Restrict calls
// gets distinct entries (mirrors the staging registrar's clone).
cp := *rule
cp.Allow = append([]string(nil), rule.Allow...)
cp.Deny = append([]string(nil), rule.Deny...)
cp.Identities = append([]Identity(nil), rule.Identities...)
b.rules = append(b.rules, &cp)
return b
}
// EmbeddedSkills contributes a SkillsOverlay (see SkillsOverlay) customizing
// the CLI's embedded skill content. It implies FailClosed: although skill
// content is not a command-enforcement boundary, the overlay is a distributionView on GitHub (pinned to 7fd6ef3c07)
Solutions
- Construct a valid *Rule before calling Restrict, or skip the Restrict call entirely when no rule is needed
- Check the rule-producing function's error/nil return before passing its result to Restrict
- Call Build() and inspect the joined error; b.errs accumulates, so fix the nil input and rebuild
Example fix
// before
var rule *Rule
b.Restrict(rule) // panics-free but records error
// after
if rule != nil {
b = b.Restrict(rule)
} Defensive patterns
Strategy: validation
Validate before calling
if rule == nil {
return nil, fmt.Errorf("cannot build plugin: restrict rule is nil")
}
b := builder.Restrict(rule) Type guard
func hasRule(r *Rule) bool { return r != null() } Prevention
- Never pass a possibly-nil *Rule to Restrict; nil-check or skip the call
- Let helper functions return (*Rule, error) and propagate errors instead of nil
- Call Build()/MustBuild in tests to surface accumulated builder errors early
When it happens
Trigger: Calling builder.Restrict(nil), typically because a *Rule variable is nil (uninitialized pointer, a function that returned nil on failure, or a conditional that left the rule unset).
Common situations: Config parsing produced no rule but the code still calls Restrict(rule); refactoring moved rule construction and left a nil default; optional rule built only under a feature flag that is off.
Related errors
- EmbeddedSkills(nil): spec must not be nil
- EmbeddedSkills() called more than once; a plugin owns at mos
- Restrict() requires FailClosed; do not call FailOpen() after
- EmbeddedSkills() requires FailClosed; do not call FailOpen()
- Invalid column: {column!r}
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/985a3cca132d0154.
Report an issue: GitHub.