{"record":{"id":"1159d67542b783ba","repo":"mastra-ai/mastra","slug":"invalid-skill-name-name-names-must-start-wit-1159d6","errorCode":null,"errorMessage":"Invalid skill name \"${name}\". Names must start with alphanumeric and contain only letters, numbers, hyphens, and underscores.","messagePattern":"Invalid skill name \"(.+?)\"\\. Names must start with alphanumeric and contain only letters, numbers, hyphens, and underscores\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"packages/server/src/server/handlers/workspace.ts","lineNumber":1292,"sourceCode":"      }\n      return handleError(error, 'Error fetching popular skills');\n    }\n  },\n});\n\n// =============================================================================\n// Skills API helpers\n// =============================================================================\n\n/**\n * Validate skill name to prevent path traversal attacks.\n * Only allows alphanumeric characters, hyphens, and underscores.\n */\nconst SKILL_NAME_REGEX = /^[a-z0-9][a-z0-9-_]*$/i;\n\nfunction assertSafeSkillName(name: string): string {\n  if (!SKILL_NAME_REGEX.test(name)) {\n    throw new HTTPException(400, {\n      message: `Invalid skill name \"${name}\". Names must start with alphanumeric and contain only letters, numbers, hyphens, and underscores.`,\n    });\n  }\n  return name;\n}\n\n/**\n * Validate that a file path is safe (no traversal, no absolute paths).\n * Prevents malicious API responses from writing files outside the skill directory.\n */\nfunction assertSafeFilePath(filePath: string): string {\n  // Reject absolute paths\n  if (filePath.startsWith('/') || /^[a-zA-Z]:/.test(filePath)) {\n    throw new HTTPException(400, {\n      message: `Invalid file path \"${filePath}\". Absolute paths are not allowed.`,\n    });\n  }\n  // Reject path traversal attempts","sourceCodeStart":1274,"sourceCodeEnd":1310,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/workspace.ts#L1274-L1310","documentation":"assertSafeSkillName validates skill names against SKILL_NAME_REGEX (/^[a-z0-9][a-z0-9-_]*$/i): must start with an alphanumeric and contain only letters, numbers, hyphens, and underscores. Anything else (spaces, dots, slashes, leading hyphen, unicode) triggers a 400.","triggerScenarios":"Any route that calls assertSafeSkillName with a name like 'my skill', '.hidden', 'skill.v2', '/etc/passwd', or a name starting with '-' or '_'.","commonSituations":"Deriving the name from a filename (e.g. 'README.md'); user-supplied names with spaces or dots; path fragments accidentally passed as names; non-ASCII names from other locales.","solutions":["Sanitize the name: lowercase, replace invalid characters with '-', strip leading non-alphanumerics.","Trim file extensions before using a filename as a skill name.","Validate on the client with the same regex before calling the API.","If the name is inherently unsafe, use the ?path= disambiguation parameter instead of embedding it as a name."],"exampleFix":"// before\nconst name = 'My Skill.v2';\n// after\nconst name = 'My Skill.v2'.toLowerCase().replace(/[^a-z0-9-_]+/g, '-').replace(/^[^a-z0-9]+/, '');","handlingStrategy":"validation","validationCode":"const SKILL_NAME_REGEX = /^[a-z0-9][a-z0-9-_]*$/i;\nif (!SKILL_NAME_REGEX.test(name)) {\n  throw new Error(`Skill name \"${name}\" is invalid; use [a-z0-9][a-z0-9-_]*`);\n}","typeGuard":"function isValidSkillName(name: string): boolean {\n  return /^[a-z0-9][a-z0-9-_]*$/i.test(name);\n}","tryCatchPattern":"try {\n  return await client.getSkillByName(name);\n} catch (e) {\n  if (isHttpException(e, 400) && String(e.message).includes('Invalid skill name')) {\n    return await client.getSkillByName(sanitizeSkillName(name));\n  }\n  throw e;\n}","preventionTips":["Sanitize names derived from filenames (strip extensions, replace invalid chars with '-').","Validate names with the same regex client-side before any API call.","Never pass raw path fragments as skill names.","Normalize user input (trim, lowercase) before sending."],"tags":["http-400","validation","naming","skills"],"backgroundTag":"invalid-identifier-format","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}