{"record":{"id":"418d479008c4de4a","repo":"mastra-ai/mastra","slug":"skillpath-does-not-exist-on-the-server-filesystem","errorCode":null,"errorMessage":"skillPath does not exist on the server filesystem: ${resolvedPath}. Create the skill directory (with a SKILL.md) before publishing, or use a skill that was materialized to disk.","messagePattern":"skillPath does not exist on the server filesystem: (.+?)\\. Create the skill directory \\(with a SKILL\\.md\\) before publishing, or use a skill that was materialized to disk\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"packages/server/src/server/handlers/stored-skills.ts","lineNumber":630,"sourceCode":"      const resolvedPath = path.default.resolve(skillPath);\n      const allowedBase = path.default.resolve(process.env.SKILLS_BASE_DIR || process.cwd());\n      if (!resolvedPath.startsWith(allowedBase + path.default.sep) && resolvedPath !== allowedBase) {\n        throw new HTTPException(400, {\n          message: `skillPath must be within the allowed directory: ${allowedBase}`,\n        });\n      }\n\n      // Verify the source directory exists and contains a SKILL.md before attempting\n      // to publish, so callers get a 400 with context instead of a raw 500/ENOENT.\n      try {\n        const stat = await fs.stat(resolvedPath);\n        if (!stat.isDirectory()) {\n          throw new HTTPException(400, { message: `skillPath is not a directory: ${resolvedPath}` });\n        }\n      } catch (err) {\n        if (err instanceof HTTPException) throw err;\n        if ((err as NodeJS.ErrnoException)?.code === 'ENOENT') {\n          throw new HTTPException(400, {\n            message: `skillPath does not exist on the server filesystem: ${resolvedPath}. Create the skill directory (with a SKILL.md) before publishing, or use a skill that was materialized to disk.`,\n          });\n        }\n        throw err;\n      }\n      try {\n        await fs.stat(path.default.join(resolvedPath, 'SKILL.md'));\n      } catch (err) {\n        if ((err as NodeJS.ErrnoException)?.code === 'ENOENT') {\n          throw new HTTPException(400, {\n            message: `skillPath is missing SKILL.md: ${resolvedPath}`,\n          });\n        }\n        throw err;\n      }\n\n      // Use LocalSkillSource to read from the server filesystem\n      const source = new LocalSkillSource();","sourceCodeStart":612,"sourceCodeEnd":648,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/stored-skills.ts#L612-L648","documentation":"A 400 thrown when `fs.stat(resolvedPath)` fails with ENOENT — the `skillPath` directory does not exist on the SERVER's filesystem. The handler checks up front so callers get a clear 400 instead of a raw 500/ENOENT deeper in the publish flow. Note this checks the server host, so a path valid on a client machine can still be missing on the server.","triggerScenarios":"Publishing a skillPath that was never created, was deleted, exists only on the caller's local machine against a remote server, or uses a relative path that resolves differently under the server's cwd.","commonSituations":"Local dev path sent to a deployed server; typo in the directory name; publishing before materializing a skill to disk; containerized deployments where the path was not volume-mounted.","solutions":["Create the skill directory (including SKILL.md) on the server before publishing, or use a skill previously materialized to disk","Mount the skills directory into the container / ensure SKILLS_BASE_DIR points at the mounted volume","Check existence locally against the server's view: `fs.stat(path.resolve(SKILLS_BASE_DIR, relPath))`","For remote servers, upload/materialize the skill first (or use an API-supported source) instead of referencing local paths"],"exampleFix":"// before\nawait client.publishStoredSkill({ skillPath: './skills/my-skill' }); // missing on server\n// after\n// server: mkdir -p /srv/skills/my-skill && create SKILL.md, SKILLS_BASE_DIR=/srv/skills\nawait client.publishStoredSkill({ skillPath: '/srv/skills/my-skill' });","handlingStrategy":"validation","validationCode":"import fs from 'node:fs/promises';\nawait fs.access(path.resolve(skillPath)); // throws ENOENT locally first; ensure the same path exists on the server","typeGuard":null,"tryCatchPattern":"try { await publishStoredSkill({ skillPath }); } catch (e) {\n  if (e.status === 400 && /does not exist on the server filesystem/.test(e.message)) {\n    throw new Error('Create the skill directory (with SKILL.md) on the server, or materialize the skill to disk first');\n  }\n  throw e;\n}","preventionTips":["Materialize/create the skill directory on the server host before publishing","Mount the skills volume in containers and align SKILLS_BASE_DIR","Use absolute server-side paths, not client-relative ones","Pre-check with a listing endpoint or ssh fs.stat before publishing"],"tags":["filesystem","bad-request","deployment"],"backgroundTag":"file-not-found-enoent","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}