mastra-ai/mastra · error · HTTPException

Could not find skill "${skillName}" for ${owner}/${repo}

Error message

Could not find skill "${skillName}" for ${owner}/${repo}

What it means

HTTPException 404 thrown by the fetch-skill-instructions handler when the skills.sh content endpoint (${SKILLS_SH_API_URL}/api/skills/{owner}/{repo}/{skillName}/content) responds with a non-ok status, meaning the named skill could not be retrieved for that owner/repo.

Source

Thrown at packages/server/src/server/handlers/workspace.ts:1382

  path: '/workspaces/:workspaceId/skills-sh/preview',
  responseType: 'json',
  pathParamSchema: workspaceIdPathParams,
  queryParamSchema: skillsShPreviewQuerySchema,
  responseSchema: skillsShPreviewResponseSchema,
  summary: 'Preview skill content',
  description: 'Fetches the skill content from the Skills API.',
  tags: ['Workspace', 'Skills'],
  handler: async ({ owner, repo, path: skillName }) => {
    try {
      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), 10000);

      const url = `${SKILLS_SH_API_URL}/api/skills/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/${encodeURIComponent(skillName)}/content`;
      const response = await fetch(url, { signal: controller.signal });
      clearTimeout(timeoutId);

      if (!response.ok) {
        throw new HTTPException(404, {
          message: `Could not find skill "${skillName}" for ${owner}/${repo}`,
        });
      }

      const data = (await response.json()) as { instructions: string; raw: string };
      const content = data.instructions || data.raw || '';

      if (!content) {
        throw new HTTPException(404, {
          message: `No content available for skill "${skillName}"`,
        });
      }

      return { content };
    } catch (error) {
      if (error instanceof HTTPException) {
        throw error;
      }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Verify the exact skill name and owner/repo slugs against the skills.sh registry before calling.
  2. Check that the repository is public (or provide credentials the upstream API accepts).
  3. If the skill was renamed, update the request to the new skill identifier; handle the 404 gracefully in the client UI.

Example fix

// before
await fetch(`/api/workspaces/${id}/skills/instructions?skillName=SkilName`);
// after
await fetch(`/api/workspaces/${id}/skills/instructions?skillName=SkillName`); // exact registry name
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate identifiers before calling
function isValidSlug(s) { return typeof s === 'string' && /^[a-zA-Z0-9._-]+$/.test(s); }
if (!isValidSlug(skillName) || !isValidSlug(owner) || !isValidSlug(repo)) throw new Error('Invalid owner/repo/skillName');

Type guard

function isSkillNotFound(e: unknown): boolean {
  return e instanceof Error && /Could not find skill/.test(e.message);
}

Try / catch

try {
  const { content } = await fetchSkillInstructions(owner, repo, skillName);
} catch (e) {
  if (isSkillNotFound(e)) {
    console.warn(`Skill ${skillName} not found in ${owner}/${repo}; check the registry slug.`);
    return null; // graceful degradation
  }
  throw e;
}

Prevention

When it happens

Trigger: GET on the workspace skill-instructions route with an owner/repo/skillName combination for which the upstream content endpoint returns 404 or any other non-ok response.

Common situations: Typo in skill name or repo slug; skill renamed or unpublished; repo is private so the content endpoint cannot see it; case mismatch between requested and registered skill name.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/1d3c71e90143adb8. Report an issue: GitHub.