{"record":{"id":"74070914deacded9","repo":"mastra-ai/mastra","slug":"directory-not-found-in-composite-skill-source-p","errorCode":null,"errorMessage":"Directory not found in composite skill source: ${path}","messagePattern":"Directory 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":188,"sourceCode":"      for (const dirName of this.#sources.keys()) {\n        entries.push({ name: dirName, type: 'directory' });\n        seen.add(dirName);\n      }\n\n      // Also list fallback skills\n      for (const dirName of this.#fallbackSkills) {\n        if (!seen.has(dirName)) {\n          entries.push({ name: dirName, type: 'directory' });\n          seen.add(dirName);\n        }\n      }\n\n      return entries;\n    }\n\n    const route = this.#routePath(path);\n    if (!route) {\n      throw new Error(`Directory not found in composite skill source: ${path}`);\n    }\n\n    return route.source.readdir(route.subPath);\n  }\n\n  async realpath(path: string): Promise<string> {\n    const normalized = this.#normalizePath(path);\n    if (normalized === '') return '';\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    const realSubPath = route.source.realpath ? await route.source.realpath(route.subPath) : route.subPath;\n    return [route.mountDir, realSubPath].filter(Boolean).join('/');\n  }\n}","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/workspace/skills/composite-versioned-skill-source.ts#L170-L206","documentation":"CompositeVersionedSkillSource.readdir throws this when #routePath cannot resolve the requested directory to any mounted skill version or fallback source. The composite serves the virtual root itself (readdir('') lists all mounted skills), but any subdirectory must live inside a mounted skill tree or the fallback filesystem source.","triggerScenarios":"Calling readdir with a directory path whose first segment does not match any mounted skill dirName and which is not servable by the configured fallback source; also thrown for paths that normalize away to an unroutable value when no fallback exists.","commonSituations":"Listing a skill directory that was renamed or republished under a different dirName; scanning '/assets' at the composite root instead of '/<skill>/assets'; stale cached skill names after a republish removed the version from storage.","solutions":["List the mounted skills with readdir('') and use one of the returned directory names as the first path segment.","Confirm the skill's VersionedSkillEntry (dirName/tree) was included when the composite source was constructed.","Ensure a fallback SkillSource is configured if the directory belongs to a live (unpublished) skill.","Guard with exists(path) before calling readdir to convert the failure into a controlled branch."],"exampleFix":"// before\nawait source.readdir('references'); // no such top-level dir\n// after\nawait source.readdir('brand-guidelines/references');","handlingStrategy":"validation","validationCode":"if (!(await source.exists(dir))) {\n  return []; // or surface a friendly 'no such directory' to the UI\n}\nconst entries = await source.readdir(dir);","typeGuard":null,"tryCatchPattern":"try {\n  return await source.readdir(dir);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Directory not found in composite skill source')) {\n    return [];\n  }\n  throw err;\n}","preventionTips":["Enumerate mounted skills with readdir('') before descending.","Treat the composite root as virtual — never expect arbitrary top-level dirs.","Verify skill dirNames passed to the constructor match the names used at runtime."],"tags":["filesystem","skills","path-resolution","not-found"],"backgroundTag":"directory-not-found","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}