larksuite/cli · error

cannot inspect installed lark-suite: global skills JSON did

Error message

cannot inspect installed lark-suite: global skills JSON did not include its path

What it means

localOfficialSkills builds the list of locally-installed official skills. When the previous state indicates suite layout, it locates the installed 'lark-suite' entry in the global skills JSON and inspects its references directory. This error is thrown when a 'lark-suite' entry exists but its Path field is empty, meaning the listing did not include install-location metadata, so the tool cannot determine where the suite is installed to enumerate its references.

Source

Thrown at internal/skillscheck/sync.go:400

	}
	return nil, fmt.Errorf("local skills list failed")
}

func localOfficialSkills(installed []installedSkill, previous *SkillsState, readable bool) ([]string, error) {
	if !readable || previous == nil || EffectiveLayout(previous) == LayoutSeparate {
		names := make([]string, 0, len(installed))
		for _, skill := range installed {
			names = append(names, skill.Name)
		}
		return names, nil
	}

	for _, skill := range installed {
		if skill.Name != "lark-suite" {
			continue
		}
		if skill.Path == "" {
			return nil, fmt.Errorf("cannot inspect installed lark-suite: global skills JSON did not include its path")
		}
		return listDirectSubdirs(filepath.Join(skill.Path, "references"))
	}
	return nil, fmt.Errorf("cannot inspect installed lark-suite: skill is not installed")
}

func listDirectSubdirs(root string) ([]string, error) {
	entries, err := vfs.ReadDir(root)
	if err != nil {
		return nil, err
	}
	names := []string{}
	for _, entry := range entries {
		if entry.IsDir() {
			names = append(names, entry.Name())
		}
	}
	sort.Strings(names)

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Reinstall lark-suite globally so the host CLI produces a fresh listing including the install path, then re-run sync.
  2. Clear the cached skills state so localOfficialSkills takes the name-only branch instead of requiring the path.
  3. Upgrade the host CLI so its global skills JSON format includes path metadata for every installed skill.
  4. Inspect the global skills JSON (`lark skills list --json` or equivalent) to confirm the lark-suite entry includes a path; if not, report or fix the CLI version emitting it.

Example fix

// before: name-only installed list used in suite layout
//   installed := [{Name: "lark-suite", Path: ""}]
//   names, err := localOfficialSkills(installed, previous, true) // -> error
// after: degrade gracefully when path metadata is absent
if skill.Path == "" {
    // fall back to name-only enumeration instead of failing
    return namesFromInstalled(installed), nil
}
return listDirectSubdirs(filepath.Join(skill.Path, "references"))
Defensive patterns

Strategy: validation

Validate before calling

installed, err := listInstalledSkills(runner)
if err != nil { return err }
if readable && previous != nil && EffectiveLayout(previous) != LayoutSeparate {
    suite, ok := findSkill(installed, "lark-suite")
    if !ok {
        return fmt.Errorf("state says suite layout but lark-suite is not installed")
    }
    if suite.Path == "" {
        // listing lacks path metadata; refresh listing JSON or clear state first
        return fmt.Errorf("global skills listing lacks path for lark-suite")
    }
}

Type guard

func hasInstallPath(s installedSkill) bool { return s.Path != "" }

func findSkill(installed []installedSkill, name string) (installedSkill, bool) {
    for _, s := range installed {
        if s.Name == name { return s, true }
    }
    return installedSkill{}, false
}

Try / catch

names, err := localOfficialSkills(installed, previous, readable)
if err != nil {
    if strings.Contains(err.Error(), "global skills JSON did not include its path") {
        // degrade to name-only enumeration and let sync rebuild the state
        names = namesFromInstalled(installed)
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: Calling SyncSkills (via localOfficialSkills) when the previous skills state reports suite layout, the global skills listing was parsed successfully and contains a 'lark-suite' entry, but that entry has an empty Path — typically because the listing only carries skill names (e.g. derived from the text fallback in listInstalledSkills, which builds installedSkill{Name: name} without a path).

Common situations: The host CLI's JSON listing failed so the code fell back to the name-only text listing; an older CLI version emits JSON without path fields; the global skills JSON was hand-edited or corrupted; or the state file says suite layout while the listing format changed between CLI versions.

Related errors


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