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
- Confirm a SKILL.md file exists at the target path with valid frontmatter (name, description, etc.).
- If the skill is in a subfolder, pass the correct `subpath` so sourcePath resolves onto it.
- Validate the SKILL.md frontmatter locally (YAML lint) and fix any parse errors.
- 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
- Verify SKILL.md and its frontmatter before publishing a skill.
- Point install commands at the exact skill folder or supply the correct subpath.
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
- Invalid skill name: Path traversal detected.
- Invalid path: Directory traversal not allowed.
- The path "${trimmedPath}" is not a directory.
- The path "${trimmedPath}" does not exist.
- Unsupported file extension for extraction: ${file}
AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12).
Data as JSON: /api/errors/5444ca16672f0d6b.
Report an issue: GitHub.