mastra-ai/mastra · warning · HTTPException

No content available for skill "${skillName}"

Error message

No content available for skill "${skillName}"

What it means

HTTPException 404 thrown when the skills.sh content endpoint returned successfully but both 'instructions' and 'raw' fields are empty/missing, so there is no usable content for the requested skill. The handler builds content = data.instructions || data.raw || '' and throws if it is empty.

Source

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

    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;
      }
      return handleError(error, 'Error fetching skill preview');
    }
  },
});

// =============================================================================
// skills.sh Install Route
// =============================================================================

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Verify the skill has content on skills.sh; if not, publish or add instructions/raw content for it.
  2. Handle the 404 in the client and fall back to reading the skill's SKILL.md directly from the repo.
  3. If this appeared suddenly, check whether the upstream response schema changed (field names no longer 'instructions'/'raw').

Example fix

// before
const { content } = await fetchInstructions(skillName); // throws when empty
// after
const res = await fetchInstructions(skillName).catch(() => null);
const content = res?.content ?? (await fetchRawSkillMdFromRepo(owner, repo, skillName));
Defensive patterns

Strategy: fallback

Validate before calling

// Cannot pre-validate content, but validate the response shape when you can call the API directly
const data = await res.json();
if (!data || (!data.instructions && !data.raw)) throw new Error('Skill has no content upstream');

Type guard

function hasSkillContent(d: unknown): d is { instructions?: string; raw?: string } {
  const o = d as any;
  return !!o && (typeof o.instructions === 'string' && o.instructions.length > 0 || typeof o.raw === 'string' && o.raw.length > 0);
}

Try / catch

try {
  return await fetchSkillInstructions(owner, repo, skillName);
} catch (e) {
  if (/No content available/.test(String(e))) {
    return fetchFallbackFromRepo(owner, repo, skillName); // e.g. raw SKILL.md from GitHub
  }
  throw e;
}

Prevention

When it happens

Trigger: Requesting instructions for a skill whose registry entry exists but has no instructions or raw content populated upstream (empty strings or absent fields in the JSON response).

Common situations: Newly published skills with no README/instructions yet; upstream schema changes renaming the content fields; skills whose content failed to index on skills.sh.

Related errors


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