mastra-ai/mastra · error
SKILL.md not found in skill files
Error message
SKILL.md not found in skill files
What it means
parseSkillSnapshotFromFiles builds a publishable skill snapshot from a collected file list and requires a file at path 'SKILL.md' to parse frontmatter and metadata from. If the file list contains no entry with exactly that path, publishing cannot proceed and this error is thrown. It is wrapped by collectSkillForPublish to add the skill path context (see error 2064).
Source
Thrown at packages/core/src/workspace/skills/publish.ts:226
* Parse a flat array of skill files into a denormalized snapshot.
*
* Finds `SKILL.md`, parses its YAML frontmatter into structured fields
* (name, description, license, compatibility, metadata), and uses the
* markdown body as `instructions`. Discovers `references/`, `scripts/`,
* and `assets/` subdirectory paths from the file list.
*
* Used by both the publish flow (which has files from a SkillSource walk)
* and the registry install flow (which has files fetched from an external
* registry like skills.sh). The Agent Skills spec puts metadata in
* frontmatter and agent-facing prose in the body — this helper enforces
* that split so frontmatter never leaks into the runtime instructions.
*
* @throws if `SKILL.md` is missing from the file list
*/
export function parseSkillSnapshotFromFiles(files: SkillSnapshotFile[]): Omit<StorageSkillSnapshotType, 'tree'> {
const skillMdFile = files.find(f => f.path === 'SKILL.md');
if (!skillMdFile) {
throw new Error('SKILL.md not found in skill files');
}
const skillMdContent =
typeof skillMdFile.content === 'string' ? skillMdFile.content : skillMdFile.content.toString('utf-8');
const parsed = matter(skillMdContent);
const frontmatter = parsed.data;
const instructions = parsed.content.trim();
const allPaths = files.map(f => f.path);
const references = collectSubdirPaths(allPaths, 'references');
const scripts = collectSubdirPaths(allPaths, 'scripts');
const assets = collectSubdirPaths(allPaths, 'assets');
return {
name: frontmatter.name,
description: frontmatter.description,
instructions,
license: frontmatter.license,View on GitHub (pinned to 75dd419e61)
Solutions
- Ensure the skill directory contains a file at its root named exactly 'SKILL.md' (case-sensitive).
- If calling parseSkillSnapshotFromFiles directly, prepend { path: 'SKILL.md', content: ... } to the files array.
- Check the file collection logic isn't excluding SKILL.md via ignore/glob filters.
- Catch this error in callers and surface which directory was scanned.
Example fix
// before
const snapshot = parseSkillSnapshotFromFiles([{ path: 'skill.md', content }]);
// after
const snapshot = parseSkillSnapshotFromFiles([{ path: 'SKILL.md', content }]); Defensive patterns
Strategy: validation
Validate before calling
const hasSkillMd = files.some(f => f.path === 'SKILL.md');
if (!hasSkillMd) {
throw new Error(`Cannot parse snapshot: files must include 'SKILL.md' (got: ${files.map(f => f.path).join(', ')})`);
} Type guard
function hasSkillMd(files: SkillSnapshotFile[]): files is [SkillSnapshotFile, ...SkillSnapshotFile[]] & { 0: { path: 'SKILL.md' } } {
return files.some(f => f.path === 'SKILL.md');
} Try / catch
try {
return parseSkillSnapshotFromFiles(files);
} catch (err) {
if (err instanceof Error && err.message === 'SKILL.md not found in skill files') {
// report which directory/file list was scanned
}
throw err;
} Prevention
- Every skill directory must contain a root-level, exactly-cased 'SKILL.md'.
- Check glob/ignore filters don't exclude SKILL.md.
- Validate the file list before parsing in publish pipelines.
When it happens
Trigger: Calling parseSkillSnapshotFromFiles with a SkillSnapshotFile[] that lacks an entry with path === 'SKILL.md' — e.g. files gathered from a directory that only has supporting assets, or the file was named 'skill.md' (case mismatch) or nested ('docs/SKILL.md').
Common situations: A skill folder missing its SKILL.md manifest; case-sensitive filesystem vs. lowercase filename; the collect step filtered out SKILL.md; hand-building the file list for tests and forgetting the manifest.
Related errors
- SKILL.md not found in ${skillPath}
- Invalid skill "${name}": ${validation.errors.join('; ')}
- Invalid skill metadata in ${filePath}: ${validation.errors.j
- Invalid ${label} path: ${input}
- Invalid skill name "${name}". Names must start with alphanum
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/4b514159012edef8.
Report an issue: GitHub.