{"record":{"id":"c1e658bf64b132ef","repo":"mastra-ai/mastra","slug":"path-not-found-in-composite-skill-source-path","errorCode":null,"errorMessage":"Path not found in composite skill source: ${path}","messagePattern":"Path 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":147,"sourceCode":"  }\n\n  async stat(path: string): Promise<SkillSourceStat> {\n    const normalized = this.#normalizePath(path);\n\n    // Root directory\n    if (normalized === '') {\n      return {\n        name: '.',\n        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","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/workspace/skills/composite-versioned-skill-source.ts#L129-L165","documentation":"CompositeVersionedSkillSource.stat routes a virtual path to the underlying per-version skill source via #routePath. When the path does not match any registered version prefix (e.g. a version directory that does not exist), it throws this error instead of delegating. It indicates the requested path is not part of the composite skill's versioned namespace.","triggerScenarios":"Calling stat()/readFile() with a path whose top-level version segment is not a registered version (e.g. 'v99/file.md' when only v1/v2 exist); a bare path without a version prefix that no route accepts; stale version references after a skill version was removed or renamed.","commonSituations":"Hardcoded version strings in tooling after versions were pruned; listing paths from one source and stat'ing them against another (different) composite source; typos in version folder names ('v1' vs '1.0'); automation reading latest-version paths cached before a re-index.","solutions":["List available paths first (e.g. via list/read of the composite source root) and use an exact existing version prefix in the path.","Normalize the version segment against registered versions before calling stat (resolve 'latest' or partial versions to a concrete registered version).","Refresh any cached version listings after skill versions are added/removed, and retry with the corrected path."],"exampleFix":"// before\nawait source.stat('v3/skill.md'); // v3 not registered -> throws\n// after\nconst entries = await source.list('/');\nconst path = entries.some(e => e.path === 'v3') ? 'v3/skill.md' : `${entries[0].path}/skill.md`;\nawait source.stat(path);","handlingStrategy":"try-catch","validationCode":"async function safeStat(source, path) {\n  const entries = await source.list('/');\n  if (!entries.some(e => path === e.path || path.startsWith(e.path + '/'))) {\n    throw new Error(`Path ${path} not in registered versions: ${entries.map(e => e.path).join(', ')}`);\n  }\n  return source.stat(path);\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await source.stat(path);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Path not found in composite skill source')) {\n    const versions = await source.list('/');\n    console.error(`Unknown path ${path}; available: ${versions.map(v => v.path).join(', ')}`);\n    // resolve to a registered version or surface a user-facing not-found\n    return null;\n  }\n  throw err;\n}","preventionTips":["Refresh cached version listings whenever skill versions are added or removed.","Never hardcode version strings; resolve 'latest' through the source's own metadata (e.g. maxVersionCreatedAt entries).","Validate user-supplied version segments against the registered list before composing paths.","Stat paths only against the same composite source instance that produced them."],"tags":["filesystem","path","skills"],"backgroundTag":"path-not-found","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}