mastra-ai/mastra · error · HTTPException
No content available for skill "${skillName}"
Error message
No content available for skill "${skillName}" What it means
After a successful skills.sh response, previewSkillsSh extracts content from the JSON body (instructions or raw fields). If both are empty/missing, the skill technically exists but has no usable content, so the route throws HTTPException 404. This prevents returning an empty preview to the UI.
Source
Thrown at packages/server/src/server/handlers/skills-sh-shared.ts:240
const url = `${SKILLS_SH_API_URL}/api/skills/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/${encodeURIComponent(skillName)}/content`;
const response = await fetch(url, { signal: controller.signal });
if (!response.ok) {
if (response.status === 404) {
throw new HTTPException(404, {
message: `Could not find skill "${skillName}" for ${owner}/${repo}`,
});
}
throw new HTTPException(502, {
message: `Skills API error: ${response.status} ${response.statusText}`,
});
}
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 };
} finally {
clearTimeout(timeoutId);
}
}
/**
* Fetch the full file tree for a skill from the skills.sh files endpoint.
* Returns null when the skill doesn't exist (404). Throws on other upstream
* errors. Caller is responsible for validating each returned file path with
* `assertSafeFilePath` before writing to disk.
*/
export async function fetchSkillFiles(
owner: string,View on GitHub (pinned to 75dd419e61)
Solutions
- Verify the skill's SKILL.md/content is actually published on skills.sh
- Re-publish or push the skill content to the source repo and let skills.sh re-index
- If the API shape changed, update the data.instructions || data.raw extraction to match the new field names
- Surface a 'skill has no content' state in the UI instead of an empty preview
Example fix
// before const content = data.instructions || data.raw || ''; // after (also check alternate fields) const content = data.instructions || data.raw || data.content || '';
Defensive patterns
Strategy: fallback
Validate before calling
// Can't be checked before the call; validate after receiving the payload
const hasContent = (d: { instructions?: string; raw?: string }) => Boolean(d.instructions || d.raw); Type guard
function hasSkillContent(d: unknown): d is { instructions: string } | { raw: string } {
const o = d as any;
return typeof o === 'object' && o !== null && (typeof o.instructions === 'string' && o.instructions.length > 0 || typeof o.raw === 'string' && o.raw.length > 0);
} Try / catch
let preview;
try {
preview = await api.previewSkill(owner, repo, name);
} catch (e) {
if (isEmptyContentError(e)) preview = { content: null, note: 'Skill published but has no content' };
else throw e;
} Prevention
- Ensure SKILL.md/content is committed and pushed before publishing a skill
- Render an explicit empty-content state in the preview UI
- Spot-check the skills.sh payload shape when upgrading
When it happens
Trigger: Previewing a skill whose skills.sh content payload contains neither 'instructions' nor 'raw' (or both are empty strings); the upstream 200 response has no content fields.
Common situations: Skill published with an empty SKILL.md; skills.sh indexing a repo but failing to extract content; skill metadata present but content not yet generated; API schema change upstream.
Related errors
- Could not find skill "${skillName}" for ${owner}/${repo}
- No content available for skill "${skillName}"
- Model "${modelId}" is not available. Available models: ${ids
- ACP connection is not initialized
- Model "${this.options.model}" is not available. Available mo
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/73677879f9a67567.
Report an issue: GitHub.