larksuite/cli · error

v0.2 index contains no skills

Error message

v0.2 index contains no skills

What it means

fetchOfficialSkills returns this sentinel when the index parsed successfully as v0.2 JSON but the resulting official skills list is empty. An empty index cannot drive a sync plan, so the source is treated as failed and SyncSkills moves on to the next source. This is a server-side/content problem, not a client parsing problem.

Source

Thrown at internal/skillscheck/sync.go:359

			Detail: strings.Join(reasons, "\n"),
			Force:  opts.Force,
		}
	}

	return fallbackSeparate(opts, previous, readable, localOfficial, installed, fallbackPlan, reasons)
}

func fetchOfficialSkills(runner SkillsRunner, source string) ([]string, error) {
	result := runner.FetchSkillsIndex(source)
	if result == nil || result.Err != nil {
		return nil, fmt.Errorf("index request failed: %s", resultDetail(result))
	}
	official, err := ParseOfficialSkillsIndexJSON(result.Stdout.String())
	if err != nil {
		return nil, fmt.Errorf("invalid v0.2 index: %w", err)
	}
	if len(official) == 0 {
		return nil, fmt.Errorf("v0.2 index contains no skills")
	}
	return official, nil
}

func listInstalledSkills(runner SkillsRunner) ([]installedSkill, error) {
	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 {

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Verify the source URL points at the production index rather than a staging or placeholder document
  2. Check with the index publisher/upstream whether the index is temporarily empty or being rebuilt
  3. Try the next configured source in SkillsSources(); if all sources are empty, sync cannot proceed
  4. If you control the source, republish the index with the full skills list
  5. Inspect the fetched JSON yourself to confirm the skills array is truly empty

Example fix

// before: silent acceptance of empty index
// after: warn and skip to next source
if len(official) == 0 {
    log.Printf("warning: %s served an empty skills index; trying next source", source)
    return nil, fmt.Errorf("v0.2 index contains no skills")
}
Defensive patterns

Strategy: fallback

Validate before calling

body := result.Stdout.String()
var idx struct{ Skills []any `json:"skills"` }
if json.Unmarshal([]byte(body), &idx) == nil && len(idx.Skills) == 0 {
    return errors.New("index is valid but empty; skip this source")
}

Try / catch

official, err := fetchOfficialSkills(runner, source)
if err != nil && err.Error() == "v0.2 index contains no skills" {
    // move to the next configured source rather than aborting
    official, err = fetchOfficialSkills(runner, nextSource)
}

Prevention

When it happens

Trigger: SyncSkills -> fetchOfficialSkills where ParseOfficialSkillsIndexJSON succeeds but returns a zero-length skills slice.

Common situations: The upstream publisher cleared or is repopulating the index; a staging/mirror source has an empty placeholder index; the wrong URL points at a valid-but-empty index document; CDN serving a stub during an outage.

Related errors


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