{"record":{"id":"742c62539e1c69c5","repo":"mastra-ai/mastra","slug":"could-not-derive-skill-id-from-registry-skill-meta","errorCode":null,"errorMessage":"Could not derive skill ID from registry skill metadata.","messagePattern":"Could not derive skill ID from registry skill metadata\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"packages/server/src/server/handlers/builder-registry.ts","lineNumber":366,"sourceCode":"        });\n      }\n\n      const safeSkillId = assertSafeSkillName(result.skillId);\n      const files = buildFileTree(result.files);\n\n      // Parse SKILL.md frontmatter into structured fields. Splitting\n      // frontmatter (name/description) from the markdown body keeps the\n      // body as the agent-facing `instructions` instead of polluting it\n      // with raw YAML metadata. SKILL.md missing or unparseable simply\n      // yields a null snapshot — registry-provided values then fill in.\n      const snapshot = parseSkillSnapshot(result.files);\n\n      const resolvedName = snapshot?.name ?? safeSkillId;\n      const description = snapshot?.description ?? `Imported from ${owner}/${repo}`;\n      const id = toSlug(resolvedName) || safeSkillId;\n\n      if (!id) {\n        throw new HTTPException(400, {\n          message: 'Could not derive skill ID from registry skill metadata.',\n        });\n      }\n\n      // Reject collisions instead of silently overwriting; UI offers \"Open existing\".\n      const existing = await skillStore.getById(id);\n      if (existing) {\n        throw new HTTPException(409, {\n          message: `Skill with id \"${id}\" already exists.`,\n          // Surface the existing id so the client can deep-link.\n          cause: { storedSkillId: id },\n        });\n      }\n\n      // Match the standard create flow: no caller = always public, otherwise default private.\n      const authorId = getCallerAuthorId(requestContext) ?? undefined;\n      const visibility: 'private' | 'public' = authorId ? (bodyVisibility ?? 'private') : 'public';\n","sourceCodeStart":348,"sourceCodeEnd":384,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/builder-registry.ts#L348-L384","documentation":"After importing files, the handler derives a skill ID by slugifying the snapshot name (falling back to the asserted safe skill name) and throws a 400 HTTPException when the derived ID is empty — i.e. neither the registry snapshot's name nor the fetched skillId yields a non-empty slug. This prevents persisting a skill with an unusable identifier.","triggerScenarios":"Installing a registry skill whose metadata lacks a usable name (empty/missing snapshot.name) AND whose skillId cannot pass assertSafeSkillName or slugify to a non-empty value.","commonSituations":"Malformed upstream registry metadata; a skill directory name composed entirely of characters stripped by toSlug (e.g. all punctuation/emoji); a registry response shape change after a server upgrade.","solutions":["Ensure the skill in the registry has a valid name in its metadata (SKILL.md frontmatter or registry manifest).","Check the upstream skill's directory/metadata naming — rename it to a normal identifier and republish.","Verify registry metadata format matches what this server version expects (upgrade server/registry pairing together).","Inspect fetchSkillFiles output to confirm skillId/snapshot.name are populated."],"exampleFix":"// before\n---\nname: \"!!!\"\ndescription: \"\"\n---\n\n// after\n---\nname: \"code-review\"\ndescription: \"Review code for issues\"\n---","handlingStrategy":"validation","validationCode":"function deriveSkillId(snapshotName?: string, fetchedId?: string): string {\n  return slugify(snapshotName ?? '') || (fetchedId ?? '') || '';\n}\nif (!deriveSkillId(meta.name, meta.skillId)) throw new Error('registry metadata has no usable name — fix upstream skill');","typeGuard":"function hasUsableName(meta: { name?: string; skillId?: string }): boolean {\n  return slugify(meta.name ?? '') !== '' || !!meta.skillId;\n}","tryCatchPattern":null,"preventionTips":["Require a valid, non-punctuation name in upstream skill metadata (SKILL.md frontmatter).","Validate registry metadata shape in CI against the expected schema.","Report upstream skills with un-sluggable names to their maintainers.","Keep registry metadata parsing and toSlug logic version-locked to the server."],"tags":["http-400","builder-registry","skills","metadata"],"backgroundTag":"invalid-resource-metadata","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}