mastra-ai/mastra · error
Directory not found in skill version tree: ${path}
Error message
Directory not found in skill version tree: ${path} What it means
VersionedSkillSource.readdir validates the normalized path against the #directories set, which is computed from the parent directories implied by the tree's file entries. If the path is not such an implied directory (including the root '' or '.'), the directory does not exist in this version and the error is thrown.
Source
Thrown at packages/core/src/workspace/skills/versioned-skill-source.ts:131
const blob = await this.#blobStore.get(entry.blobHash);
if (!blob) {
throw new Error(`Blob not found for hash ${entry.blobHash} (file: ${path})`);
}
// Decode base64-encoded binary content back to Buffer
if (entry.encoding === 'base64') {
return Buffer.from(blob.content, 'base64');
}
return blob.content;
}
async readdir(path: string): Promise<SkillSourceEntry[]> {
const normalized = this.#normalizePath(path);
if (!this.#directories.has(normalized)) {
throw new Error(`Directory not found in skill version tree: ${path}`);
}
const prefix = normalized === '' ? '' : normalized + '/';
const seen = new Set<string>();
const entries: SkillSourceEntry[] = [];
for (const filePath of Object.keys(this.#tree.entries)) {
if (!filePath.startsWith(prefix)) continue;
// Get the next segment after the prefix
const remaining = filePath.slice(prefix.length);
const nextSegment = remaining.split('/')[0];
if (!nextSegment || seen.has(nextSegment)) continue;
seen.add(nextSegment);
// If there's more after the next segment, it's a directory
const isDirectory = remaining.includes('/');
entries.push({View on GitHub (pinned to 75dd419e61)
Solutions
- Check the directory exists with exists(path) before readdir.
- List the root ('' or '.') first to see the actual structure of this version.
- Confirm the version tree actually contains files under that directory (directories are derived from file paths only).
- Republish if the directory should contain files in this version.
Example fix
// before
await versioned.readdir('assets'); // empty dir, no entries in tree
// after
await versioned.readdir(''); // list skill root Defensive patterns
Strategy: validation
Validate before calling
if (!(await versioned.exists(dir))) {
return [];
}
const entries = await versioned.readdir(dir); Try / catch
try {
return await versioned.readdir(dir);
} catch (err) {
if (err instanceof Error && err.message.startsWith('Directory not found in skill version tree')) {
return [];
}
throw err;
} Prevention
- Only expect directories that contain at least one file in the tree (dirs are derived from file paths).
- Use '' or '.' to list the skill root.
- Strip any skill-directory prefix before calling per-skill sources.
When it happens
Trigger: Calling readdir with a path that is a file, a directory that contains no files in this version, an empty-but-expected folder never committed with files, or a path outside the skill root.
Common situations: Scanning an 'assets/' folder that exists live but had no files in the published version; listing a directory added in a newer version; passing an absolute or skill-prefixed path to a per-skill source.
Related errors
- Path not found in skill version tree: ${path}
- File not found in skill version tree: ${path}
- ENOENT: no such file or directory: ${path}
- FilesystemSkillsStorage: skill with id ${id} not found
- File not found in composite skill source: ${path}
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/187dd74d13c61b58.
Report an issue: GitHub.