larksuite/cli · error
local skills list failed
Error message
local skills list failed
What it means
listInstalledSkills tries two local discovery paths: the runner's global skills JSON listing (parseInstalledSkillsJSON) and its plain-text listing (ParseSkillsList). If both fail or yield unparseable output, it returns this fixed-message error and SyncSkills aborts with Action="failed". It means the CLI cannot determine which skills are installed locally, so a safe sync plan cannot be computed.
Source
Thrown at internal/skillscheck/sync.go:383
jsonResult := runner.ListGlobalSkillsJSON()
if jsonResult != nil && jsonResult.Err == nil {
if installed, err := parseInstalledSkillsJSON(jsonResult.Stdout.String()); err == nil {
return installed, nil
}
}
textResult := runner.ListGlobalSkills()
if textResult != nil && textResult.Err == nil {
names := ParseSkillsList(textResult.Stdout.String())
if names != nil {
installed := make([]installedSkill, 0, len(names))
for _, name := range names {
installed = append(installed, installedSkill{Name: name})
}
return installed, nil
}
}
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")
}View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Run the underlying skills list command manually and check its stdout/stderr for the real failure
- Reinstall or update the skills CLI so its JSON output matches the expected schema
- Fix permissions/existence of the local skills installation directory
- Clear or repair corrupted local skills state, then retry the sync
- Check CLI version compatibility — a schema change in list output breaks both parse paths
Example fix
// before: both parse paths fail silently
installed, err := listInstalledSkills(runner) // err: local skills list failed
// after: capture raw outputs for diagnosis
jsonResult := runner.ListGlobalSkillsJSON()
if jsonResult == nil || jsonResult.Err != nil {
log.Printf("JSON listing failed: %v (stdout=%q)", errString(jsonResult), rawOf(jsonResult))
}
installed, err := listInstalledSkills(runner) Defensive patterns
Strategy: type-guard
Validate before calling
if jr := runner.ListGlobalSkillsJSON(); jr != nil && jr.Err == nil {
if _, err := parseInstalledSkillsJSON(jr.Stdout.String()); err != nil {
log.Printf("local JSON listing unparseable, falling back to text listing")
}
} Type guard
func localSkillsReadable(runner SkillsRunner) bool {
if jr := runner.ListGlobalSkillsJSON(); jr != nil && jr.Err == nil {
if _, err := parseInstalledSkillsJSON(jr.Stdout.String()); err == nil {
return true
}
}
if tr := runner.ListGlobalSkills(); tr != nil && tr.Err == nil {
return ParseSkillsList(tr.Stdout.String()) != nil
}
return false
} Try / catch
if !localSkillsReadable(runner) {
// run the list command manually, capture stderr, fix CLI/version before syncing
out, execErr := exec.Command("lark-cli", "skills", "list", "--json").CombinedOutput()
return fmt.Errorf("local skills unreadable: %v (out=%s)", execErr, out)
}
installed, err := listInstalledSkills(runner)
if err != nil { return err } Prevention
- Run the skills list command manually after upgrading the CLI to confirm output schema compatibility
- Keep the local skills directory present with correct read permissions
- Do not mutate the skills installation directory while a sync is in flight
- Test listInstalledSkills against a stub runner in CI to catch parser/CLI drift early
When it happens
Trigger: SyncSkills -> listInstalledSkills where ListGlobalSkillsJSON returns nil/Err or unparseable JSON AND ListGlobalSkills returns nil/Err or unparseable text output.
Common situations: The skills CLI binary is missing, broken, or an incompatible version; the local skills directory was deleted or has bad permissions; the JSON output format changed between CLI versions so the parser rejects it; a corrupted local state file; running in a sandbox where the CLI cannot execute.
Related errors
- parse policy yaml: %w
- %w: source %q: %w
- %w: target %q: %w
- invalid cli token %q
- must be a nonnegative integer: %w
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/3d135b6afc11770b.
Report an issue: GitHub.