larksuite/cli · error

%s: skill %q is not in the base tree

Error message

%s: skill %q is not in the base tree

What it means

validateSkillsInBase verifies that every Allow/Remove skill name exists in the snapshotted base tree. Names must pass syntax checks first (validateSkillNames); this check is semantic — the skill simply is not present in the host base or plugin Base. The resolver never silently ignores missing names.

Source

Thrown at internal/skillpolicy/resolver.go:229

	if err := validateSkillsInBase("Allow", spec.Allow, lower); err != nil {
		return err
	}
	return validateSkillsInBase("Remove", spec.Remove, lower)
}

func validateSkillNames(field string, names []string) error {
	for _, name := range names {
		if !isSkillName(name) {
			return fmt.Errorf("%s: %q is not a valid skill name", field, name)
		}
	}
	return nil
}

func validateSkillsInBase(field string, names []string, base skillTreeSnapshot) error {
	for _, name := range names {
		if _, exists := base.skills[name]; !exists {
			return fmt.Errorf("%s: skill %q is not in the base tree", field, name)
		}
	}
	return nil
}

// skillExists reports whether fsys holds a skill named name -- a
// directory carrying SKILL.md, the shape internal/skillcontent treats as
// a skill.
func skillExists(fsys fs.FS, name string) (bool, error) {
	if fsys == nil {
		return false, nil
	}
	info, err := fs.Stat(fsys, name+"/SKILL.md")
	switch {
	case err == nil:
		return !info.IsDir(), nil
	case errors.Is(err, fs.ErrNotExist) || errors.Is(err, fs.ErrInvalid):
		return false, nil

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Run `lark-cli skills list` against the same build to see the actual base skill names, then correct the entry.
  2. If the skill is contributed by this plugin's Overlay, it does not need Allow — remove the entry.
  3. If the skill was renamed upstream, update the name in the plugin spec to the new identifier.
  4. Pre-validate by scanning the base FS (or snapshot) for the name before constructing the SkillsOverlay in tests.

Example fix

// before
spec.Remove = []string{"skills-managment"}
// after
spec.Remove = []string{"skills-management"}
Defensive patterns

Strategy: validation

Validate before calling

names, err := collectBaseSkillNames(baseFS)
if err != nil { return err }
for _, n := range spec.Allow {
    if !slices.Contains(names, n) { return fmt.Errorf("%q not in base tree", n) }
}

Try / catch

if err != nil {
    var candidates []string
    return fmt.Errorf("unknown skill (run `lark-cli skills list`); did you mean one of %v?: %w", candidates, err)
}

Prevention

When it happens

Trigger: ResolveWithReferences with spec.Allow or spec.Remove naming a skill absent from lower.skills: a typo, a skill that only exists in the plugin's Overlay, or a skill removed/renamed in the CLI version being built against.

Common situations: Allow-listing a skill the plugin itself adds via Overlay (it must be in base, not the overlay, to be selectable); referencing a skill renamed upstream after a CLI upgrade; misspelling the skill directory name.

Related errors


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