PrefectHQ/fastmcp · error · ValueError
Could not read manifest for skill: {skill_name}
Error message
Could not read manifest for skill: {skill_name} What it means
`get_skill_manifest` reads the `skill://{name}/_manifest` resource from a skill server and raises this ValueError when the read returns an empty result — i.e. no content items came back for the manifest URI. It indicates the server produced nothing for the manifest resource rather than an error or malformed content.
Source
Thrown at fastmcp_slim/fastmcp/utilities/skills.py:104
async def get_skill_manifest(client: Client, skill_name: str) -> SkillManifest:
"""Get the manifest for a specific skill.
Args:
client: Connected FastMCP client
skill_name: Name of the skill
Returns:
SkillManifest with file listing
Raises:
ValueError: If manifest cannot be read or parsed
"""
manifest_uri = f"skill://{skill_name}/_manifest"
result = await client.read_resource(manifest_uri)
if not result:
raise ValueError(f"Could not read manifest for skill: {skill_name}")
content = result[0]
if isinstance(content, mcp_types.TextResourceContents):
try:
manifest_data = json.loads(content.text)
except json.JSONDecodeError as e:
raise ValueError(f"Invalid manifest JSON for skill: {skill_name}") from e
else:
raise ValueError(f"Unexpected manifest format for skill: {skill_name}")
try:
return SkillManifest(
name=manifest_data["skill"],
files=[
SkillFile(path=f["path"], size=f["size"], hash=f["hash"])
for f in manifest_data["files"]
],
)View on GitHub (pinned to 1f02114297)
Solutions
- Verify the skill exists on the target server (list skills / check the server's skill registry) before downloading.
- Check the skill server implementation actually registers a non-empty `_manifest` resource for the skill name.
- Confirm the skill name spelling — a mismatched name may resolve to an empty resource instead of a not-found error.
Example fix
// before
manifest = await get_skill_manifest(client, "code-review") # skill doesn't exist
// after
skills = await list_skills(client)
if "code-review" in skills:
manifest = await get_skill_manifest(client, "code-review") Defensive patterns
Strategy: validation
Validate before calling
async def skill_manifest_available(client, skill_name: str) -> bool:
result = await client.read_resource(f"skill://{skill_name}/_manifest")
return bool(result) Type guard
def has_text_content(result) -> bool:
import mcp.types as mcp_types
return bool(result) and isinstance(result[0], mcp_types.TextResourceContents) Try / catch
try:
manifest = await get_skill_manifest(client, skill_name)
except ValueError as e:
if "Could not read manifest" in str(e):
raise SkillNotFoundError(skill_name) from e
raise Prevention
- Verify the skill exists on the server before downloading.
- Check the skill name spelling matches the server registry exactly.
- Test custom skill servers to confirm the `_manifest` resource returns non-empty content.
When it happens
Trigger: Calling `get_skill_manifest` (directly or via `download_skill`) against a skill server that returns an empty content list for the `_manifest` resource — e.g. a server that doesn't implement the `_manifest` resource properly, returns an empty string content set, or a stub/test server misconfigured for the skill name.
Common situations: Pointing at a server that lacks the skill entirely but returns empty rather than an error, custom skill-server implementations that don't populate the manifest resource, or proxy/middleware layers that strip resource contents.
Related errors
- Invalid manifest JSON for skill: {skill_name}
- Unexpected manifest format for skill: {skill_name}
- Invalid manifest format for skill: {skill_name}
- File not found: {self.file_path}
- Skill name {skill_name!r} would escape the target directory
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/c70c98a655ced6bf.
Report an issue: GitHub.