mastra-ai/mastra · error · Error

ENOENT: no such file or directory: ${path}

Error message

ENOENT: no such file or directory: ${path}

What it means

InlineSkillSource emulates a filesystem over in-memory skill objects. stat() resolves the requested path via #getSkill; if the path does not resolve to a known inline skill (no matching skill entry), it throws this ENOENT-style error to mimic a missing file/directory. There is no real filesystem involved — only paths registered as inline skills exist.

Source

Thrown at packages/core/src/skills/inline-skill-source.ts:95

    // Root skill directory
    if (subPath === '') return true;
    // SKILL.md
    if (subPath === 'SKILL.md') return true;
    // references/ directory
    if (subPath === 'references') return (skill.references?.length ?? 0) > 0;
    // references/<file>
    if (subPath.startsWith('references/')) {
      const refPath = subPath.slice('references/'.length);
      return skill.references.includes(refPath);
    }
    return false;
  }

  async stat(path: string): Promise<SkillSourceStat> {
    const result = this.#getSkill(path);
    if (!result) {
      throw new Error(`ENOENT: no such file or directory: ${path}`);
    }

    const { skill, subPath } = result;
    const now = new Date();

    // Root skill directory
    if (subPath === '') {
      return { name: skill.name, type: 'directory', size: 0, createdAt: now, modifiedAt: now };
    }
    // SKILL.md
    if (subPath === 'SKILL.md') {
      const content = this.#skillMdCache.get(skill.name) ?? '';
      return {
        name: 'SKILL.md',
        type: 'file',
        size: Buffer.byteLength(content, 'utf-8'),
        createdAt: now,
        modifiedAt: now,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Verify the path matches an inline skill that was actually registered in this InlineSkillSource (correct prefix base and skill name).
  2. Use readdir on the prefix base first to enumerate the valid skill names.
  3. Check for case/typo differences in the skill name portion of the path.
  4. Register the skill (e.g. via createSkill and adding it to the source) before stat-ing it.

Example fix

// before
await source.stat('/inline-skills/my-skill'); // skill was named 'mySkill'
// after
await source.stat('/inline-skills/mySkill');
Defensive patterns

Strategy: type-guard

Validate before calling

const registeredSkills = await source.readdir('/inline-skills'); // or your prefix base
const names = new Set(registeredSkills.map((e) => e.name));
function skillPathExists(path) {
  const name = path.split('/').filter(Boolean).at(-1);
  return names.has(name);
}

Type guard

function isRegisteredSkillPath(path, knownSkillNames) {
  const parts = path.split('/').filter(Boolean);
  return parts.length >= 2 && knownSkillNames.includes(parts.at(-1));
}

Try / catch

try {
  const stat = await source.stat(path);
} catch (e) {
  if (String(e?.message).startsWith('ENOENT')) {
    // treat as missing: skip, or fall back to listing valid skills
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling source.stat(path) where path's skill prefix or skill name does not match any inline skill registered in the source (e.g. a typo'd skill name, or stat on a skill that was never added).

Common situations: Listing/copying skills by path derived from a different (file-based) skill source; skill names with case mismatches ('My-Skill' vs 'my-skill'); calling stat before the skill is registered, or after it was removed from the inline map.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/8be082b126e6dfe3. Report an issue: GitHub.