google-gemini/gemini-cli · error

No valid skills found in ${source}${subpath ? ` at path "${s

Error message

No valid skills found in ${source}${subpath ? ` at path "${subpath}"` : ''}. Ensure a SKILL.md file exists with valid frontmatter.

What it means

Thrown after scanning the resolved sourcePath with loadSkillsFromDir yields zero valid skills. A 'valid skill' requires a SKILL.md file with parseable, valid frontmatter; if none is found the install aborts. The message names the source and (if given) the subpath to help locate the problem.

Source

Thrown at packages/cli/src/utils/skillUtils.ts:159

      sourcePath = path.join(sourcePath, subpath);
    }

    sourcePath = path.resolve(sourcePath);

    // Quick security check to prevent directory traversal out of temp dir when cloning
    if (tempDirToClean) {
      const resolvedTemp = path.resolve(tempDirToClean);
      const relative = path.relative(resolvedTemp, sourcePath);
      if (isPathTraversal(relative)) {
        throw new Error('Invalid path: Directory traversal not allowed.');
      }
    }

    onLog(`Searching for skills in ${sourcePath}...`);
    const skills = await loadSkillsFromDir(sourcePath);

    if (skills.length === 0) {
      throw new Error(
        `No valid skills found in ${source}${subpath ? ` at path "${subpath}"` : ''}. Ensure a SKILL.md file exists with valid frontmatter.`,
      );
    }

    const workspaceDir = process.cwd();
    const storage = new Storage(workspaceDir);
    const targetDir =
      scope === 'workspace'
        ? storage.getProjectSkillsDir()
        : Storage.getUserSkillsDir();

    if (!(await requestConsent(skills, targetDir))) {
      throw new Error('Skill installation cancelled by user.');
    }

    const resolvedTarget = path.resolve(targetDir);
    await fs.mkdir(resolvedTarget, { recursive: true });

View on GitHub (pinned to 5024443c72)

Solutions

  1. Confirm a SKILL.md file exists at the target path with valid frontmatter (name, description, etc.).
  2. If the skill is in a subfolder, pass the correct `subpath` so sourcePath resolves onto it.
  3. Validate the SKILL.md frontmatter locally (YAML lint) and fix any parse errors.
  4. Check you cloned the intended repo/branch/tag.

Example fix

// before
// installSkill({ source: 'https://github.com/x/y' })  // SKILL.md is in /skills/foo

// after
// installSkill({ source: 'https://github.com/x/y', subpath: 'skills/foo' })
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
const path = require('path');
function assertSkillPresent(dir) {
  const skillFile = path.join(dir, 'SKILL.md');
  if (!fs.existsSync(skillFile)) {
    throw new Error(`No SKILL.md found under ${dir}`);
  }
  const text = fs.readFileSync(skillFile, 'utf8');
  if (!/^---[\s\S]*?---/.test(text)) {
    throw new Error('SKILL.md is missing valid frontmatter');
  }
}

Type guard

const hasValidSkillFile = (dir) => {
  const f = path.join(dir, 'SKILL.md');
  if (!fs.existsSync(f)) return false;
  return /^---[\s\S]*?---/.test(fs.readFileSync(f, 'utf8'));
};

Prevention

When it happens

Trigger: loadSkillsFromDir(sourcePath) returns an empty array. No SKILL.md exists under sourcePath, or all present SKILL.md files have invalid/missing frontmatter (missing required fields, YAML parse error).

Common situations: Pointing `source` at a repo root when the skill is in a subfolder (subpath needed). SKILL.md present but frontmatter is malformed (bad YAML, missing name/description). Cloning the wrong repo/branch. Directory contains only loose .md files not following the skill convention.

Related errors


AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12). Data as JSON: /api/errors/5444ca16672f0d6b. Report an issue: GitHub.