larksuite/cli · error
multiple plugins customized skills; only one plugin may own
Error message
multiple plugins customized skills; only one plugin may own skill content
What it means
ErrMultipleSkillsOverlays is a sentinel in internal/skillpolicy returned when more than one plugin declares a SkillsOverlay. Only one plugin may own skill content, mirroring cmdpolicy.ErrMultipleRestricts, so independent plugins cannot silently overwrite each other's skill tree. ResolveWithReferences wraps the sentinel with the list of conflicting owners, and cmd/platform_guards.go maps it to the ReasonMultipleSkillsOverlays failure reason code.
Source
Thrown at internal/skillpolicy/resolver.go:32
"io/fs"
"github.com/larksuite/cli/extension/platform"
"github.com/larksuite/cli/internal/skillref"
)
// PluginSkill pairs a plugin name with the SkillsOverlay it contributed, so a
// conflict can be attributed to specific owners. Mirrors
// cmdpolicy.PluginRule.
type PluginSkill struct {
PluginName string
SkillsOverlay *platform.SkillsOverlay
}
// ErrMultipleSkillsOverlays reports that more than one plugin tried to
// customize skill content. Mirrors cmdpolicy.ErrMultipleRestricts: only
// one owner is allowed so independent plugins cannot silently overwrite
// each other's skill tree.
var ErrMultipleSkillsOverlays = errors.New("multiple plugins customized skills; only one plugin may own skill content")
// ErrNoBaseSkillContent reports that Allow or Remove was requested against an
// empty base tree. This most often means an external wrapper main omitted
// cmd.SetEmbeddedSkillContent; exposing a sentinel lets the command layer give
// the integrator that specific recovery action instead of blaming a skill-name
// typo.
var ErrNoBaseSkillContent = errors.New("build embeds no base skill content")
// ErrInvalidHostBase reports that the wrapper-provided base skill tree is
// malformed. It is distinct from a plugin's replacement Base so diagnostics
// can direct the integrator to the correct owner.
var ErrInvalidHostBase = errors.New("host embedded skill content is invalid")
// ErrUnsatisfiedSkillDependency reports that a skill retained by the final
// composed manifest declares another skill that the manifest does not retain.
// The resolver never widens Allow or overrides Remove to repair this: an
// incomplete distribution is a build-integrity error.
var ErrUnsatisfiedSkillDependency = errors.New("composed skill tree has an unsatisfied required skill")View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Remove or disable one of the conflicting plugins so exactly one plugin owns skill content.
- If both plugins are needed, consolidate their skill customizations into a single plugin/overlay.
- Check the error text for the wrapped owner list to identify which plugins conflict before deciding which to keep.
Example fix
// before: two plugins both declare
Plugins: []Plugin{p1 /* SkillsOverlay: ... */, p2 /* SkillsOverlay: ... */}
// after: keep a single overlay owner
Plugins: []Plugin{p1 /* SkillsOverlay: ... */, p2 /* no SkillsOverlay */} Defensive patterns
Strategy: try-catch
Validate before calling
owners := 0
for _, p := range plugins {
if p.SkillsOverlay != nil { owners++ }
}
if owners > 1 { return errors.New("more than one plugin declares a SkillsOverlay") } Type guard
if errors.Is(err, skillpolicy.ErrMultipleSkillsOverlays) {
// surface owner list and ask user to keep exactly one overlay plugin
} Try / catch
if err := resolve(); err != nil {
if errors.Is(err, skillpolicy.ErrMultipleSkillsOverlays) {
// map to ReasonMultipleSkillsOverlays and show the wrapped owners
}
} Prevention
- Treat skill content ownership as single-owner: audit installed plugins for SkillsOverlay before adding a new one.
- Document in plugin guides that skill customization is exclusive.
- Surface the wrapped owner list to users so conflicts are diagnosable.
When it happens
Trigger: Calling platform/skill resolution (via cmd guards) with two or more plugins whose specs each set a non-nil SkillsOverlay, causing distinctOwners(specs) > 1 in resolver.go:79.
Common situations: Installing two plugins that both ship skill customizations; a plugin update that newly added skill content while another plugin already owned it; wrapper configurations combining a bundled plugin and a third-party one that both touch skills.
Related errors
- Missing sheet_id for sheet {title!r}
- build embeds no base skill content
- host embedded skill content is invalid
- composed skill tree has an unsatisfied required skill
- invalid skill reference remap
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/d7a9dcf7e3fdaee9.
Report an issue: GitHub.