larksuite/cli · error

composed skill tree has an unsatisfied required skill

Error message

composed skill tree has an unsatisfied required skill

What it means

ErrUnsatisfiedSkillDependency reports that a skill retained in the final composed manifest declares a required skill that the composed tree does not retain. The resolver intentionally never widens Allow or overrides Remove to repair this: an incomplete distribution is treated as a build-integrity error and fails closed. The check runs in internal/skillpolicy/dependencies.go over composed.owner's requiredSkills.

Source

Thrown at internal/skillpolicy/resolver.go:50

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")

// Resolution is the build-local result of composing embedded skill assets.
// Content serves `skills list`/`read`; References projects canonical
// CLI-authored pointers onto that same tree.
type Resolution struct {
	Content    fs.FS
	References *skillref.Resolver
}

// resolveContent is a test convenience over the production resolution path.
func resolveContent(base fs.FS, specs []PluginSkill) (fs.FS, error) {
	resolved, err := ResolveWithReferences(base, specs)
	if err != nil {
		return nil, err
	}
	return resolved.Content, nil
}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Read the wrapped error text to find which skill requires which missing dependency, then keep the dependency in the composed tree.
  2. Adjust the plugin's Allow list to include the required skill, or drop the Remove entry that deletes it.
  3. If a skill's requirement is wrong, fix the requiredSkills declaration in that skill's frontmatter so it no longer demands a skill you don't ship.

Example fix

// before
spec.Allow = []string{"skill-a"} // skill-a requires skill-b
// after
spec.Allow = []string{"skill-a", "skill-b"}
Defensive patterns

Strategy: validation

Validate before calling

func checkDeps(retained, all map[string]Skill) error {
    for name, s := range retained {
        for _, dep := range s.RequiredSkills {
            if _, ok := retained[dep]; !ok {
                return fmt.Errorf("%s requires %s which is not retained", name, dep)
            }
        }
    }
    return nil
}

Type guard

if errors.Is(err, skillpolicy.ErrUnsatisfiedSkillDependency) {
    // read wrapped message for the missing dependency name
}

Try / catch

if err := resolve(); err != nil {
    if errors.Is(err, skillpolicy.ErrUnsatisfiedSkillDependency) {
        // widen Allow or drop the offending Remove to include the dependency
    }
}

Prevention

When it happens

Trigger: Removing a skill that another retained skill requires (Remove-based), allowing a subset that omits a dependency (Allow-based), or a plugin overlay replacement whose own Base omits a skill its retained skills require — each produce the wrapped sentinel with the missing dependency name.

Common situations: Plugin authors pruning 'unused' skills that are actually runtime dependencies; tightening an Allow list after a dependency was added upstream; UTF-8 BOM or naming changes making a dependency name mismatch (see TestResolve_UTF8BOMFrontmatterMissingRequiredSkillFailsClosed).

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


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