{"record":{"id":"8ff929fb57df35e5","repo":"mastra-ai/mastra","slug":"file-not-found-in-composite-skill-source-path","errorCode":null,"errorMessage":"File not found in composite skill source: ${path}","messagePattern":"File not found in composite skill source: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/workspace/skills/composite-versioned-skill-source.ts","lineNumber":156,"sourceCode":"        type: 'directory',\n        size: 0,\n        createdAt: this.#maxVersionCreatedAt,\n        modifiedAt: this.#maxVersionCreatedAt,\n      };\n    }\n\n    const route = this.#routePath(path);\n    if (!route) {\n      throw new Error(`Path not found in composite skill source: ${path}`);\n    }\n\n    return route.source.stat(route.subPath);\n  }\n\n  async readFile(path: string): Promise<string | Buffer> {\n    const route = this.#routePath(path);\n    if (!route) {\n      throw new Error(`File not found in composite skill source: ${path}`);\n    }\n\n    return route.source.readFile(route.subPath);\n  }\n\n  async readdir(path: string): Promise<SkillSourceEntry[]> {\n    const normalized = this.#normalizePath(path);\n\n    // Root: list all mounted skill directories\n    if (normalized === '') {\n      const entries: SkillSourceEntry[] = [];\n      const seen = new Set<string>();\n\n      for (const dirName of this.#sources.keys()) {\n        entries.push({ name: dirName, type: 'directory' });\n        seen.add(dirName);\n      }\n","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/workspace/skills/composite-versioned-skill-source.ts#L138-L174","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Check that the skill version exists and was passed to the CompositeVersionedSkillSource constructor as a VersionedSkillEntry with the dirName you expect.","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.","Call exists(path) first and surface a friendly message instead of letting readFile throw."],"exampleFix":"// before\nconst content = await source.readFile('SKILL.md'); // wrong: missing skill dir\n// after\nconst content = await source.readFile('brand-guidelines/SKILL.md');","handlingStrategy":"validation","validationCode":"if (!(await source.exists(path))) {\n  const skills = await source.readdir('');\n  throw new Error(`'${path}' not found. Mounted skills: ${skills.map(s => s.name).join(', ')}`);\n}\nconst content = await source.readFile(path);","typeGuard":null,"tryCatchPattern":"try {\n  const content = await source.readFile(path);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('File not found in composite skill source')) {\n    // fall back to a default document or prompt the user\n  } else throw err;\n}","preventionTips":["Always prefix paths with the mounted skill directory name.","Call readdir('') to discover valid top-level skill dirs.","Use exists() as a pre-check before reads.","Configure a fallback source if live filesystem skills must be readable."],"tags":["filesystem","skills","path-resolution","not-found"],"backgroundTag":"file-not-found","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}