mastra-ai/mastra · error

File not found in composite skill source: ${path}

Error message

File not found in composite skill source: ${path}

What it means

CompositeVersionedSkillSource.readFile throws this when its internal router (#routePath) cannot map the requested path to any mounted skill version tree or fallback source. The composite mounts each published skill under its own directory; a path whose first segment matches no mounted skill dir and for which no fallback filesystem source is configured has no owner, so reading it is impossible. It indicates the path does not belong to any skill this composite source serves.

Source

Thrown at packages/core/src/workspace/skills/composite-versioned-skill-source.ts:156

        type: 'directory',
        size: 0,
        createdAt: this.#maxVersionCreatedAt,
        modifiedAt: this.#maxVersionCreatedAt,
      };
    }

    const route = this.#routePath(path);
    if (!route) {
      throw new Error(`Path not found in composite skill source: ${path}`);
    }

    return route.source.stat(route.subPath);
  }

  async readFile(path: string): Promise<string | Buffer> {
    const route = this.#routePath(path);
    if (!route) {
      throw new Error(`File not found in composite skill source: ${path}`);
    }

    return route.source.readFile(route.subPath);
  }

  async readdir(path: string): Promise<SkillSourceEntry[]> {
    const normalized = this.#normalizePath(path);

    // Root: list all mounted skill directories
    if (normalized === '') {
      const entries: SkillSourceEntry[] = [];
      const seen = new Set<string>();

      for (const dirName of this.#sources.keys()) {
        entries.push({ name: dirName, type: 'directory' });
        seen.add(dirName);
      }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Verify the path starts with a mounted skill directory name (e.g. 'brand-guidelines/SKILL.md'), e.g. by calling readdir('') on the composite source to list mounted skills.
  2. Check that the skill version exists and was passed to the CompositeVersionedSkillSource constructor as a VersionedSkillEntry with the dirName you expect.
  3. If the file lives on the live filesystem rather than a published version, configure the fallback SkillSource (and fallbackSkills) so unknown paths route to the live source.
  4. Call exists(path) first and surface a friendly message instead of letting readFile throw.

Example fix

// before
const content = await source.readFile('SKILL.md'); // wrong: missing skill dir
// after
const content = await source.readFile('brand-guidelines/SKILL.md');
Defensive patterns

Strategy: validation

Validate before calling

if (!(await source.exists(path))) {
  const skills = await source.readdir('');
  throw new Error(`'${path}' not found. Mounted skills: ${skills.map(s => s.name).join(', ')}`);
}
const content = await source.readFile(path);

Try / catch

try {
  const content = await source.readFile(path);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('File not found in composite skill source')) {
    // fall back to a default document or prompt the user
  } else throw err;
}

Prevention

When it happens

Trigger: Calling readFile on the composite source with a path whose top-level directory does not match any mounted skill dirName, and either no fallback source is configured or the fallback is disabled for that skill (not in fallbackSkills). Also thrown for path normalization that reduces to '' (root) only when the router returns null for unknown paths with no fallback.

Common situations: Requesting a skill that was never published or is registered under a different dirName; typos in the skill directory name; reading '/SKILL.md' directly from the root instead of '/<skill>/SKILL.md'; storage state where the version tree for a skill was deleted while clients still hold references to the old path.

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/8ff929fb57df35e5. Report an issue: GitHub.