{"record":{"id":"c70c98a655ced6bf","repo":"PrefectHQ/fastmcp","slug":"could-not-read-manifest-for-skill-skill-name","errorCode":null,"errorMessage":"Could not read manifest for skill: {skill_name}","messagePattern":"Could not read manifest for skill: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/utilities/skills.py","lineNumber":104,"sourceCode":"\nasync def get_skill_manifest(client: Client, skill_name: str) -> SkillManifest:\n    \"\"\"Get the manifest for a specific skill.\n\n    Args:\n        client: Connected FastMCP client\n        skill_name: Name of the skill\n\n    Returns:\n        SkillManifest with file listing\n\n    Raises:\n        ValueError: If manifest cannot be read or parsed\n    \"\"\"\n    manifest_uri = f\"skill://{skill_name}/_manifest\"\n    result = await client.read_resource(manifest_uri)\n\n    if not result:\n        raise ValueError(f\"Could not read manifest for skill: {skill_name}\")\n\n    content = result[0]\n    if isinstance(content, mcp_types.TextResourceContents):\n        try:\n            manifest_data = json.loads(content.text)\n        except json.JSONDecodeError as e:\n            raise ValueError(f\"Invalid manifest JSON for skill: {skill_name}\") from e\n    else:\n        raise ValueError(f\"Unexpected manifest format for skill: {skill_name}\")\n\n    try:\n        return SkillManifest(\n            name=manifest_data[\"skill\"],\n            files=[\n                SkillFile(path=f[\"path\"], size=f[\"size\"], hash=f[\"hash\"])\n                for f in manifest_data[\"files\"]\n            ],\n        )","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/utilities/skills.py#L86-L122","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nmanifest = await get_skill_manifest(client, \"code-review\")  # skill doesn't exist\n// after\nskills = await list_skills(client)\nif \"code-review\" in skills:\n    manifest = await get_skill_manifest(client, \"code-review\")","handlingStrategy":"validation","validationCode":"async def skill_manifest_available(client, skill_name: str) -> bool:\n    result = await client.read_resource(f\"skill://{skill_name}/_manifest\")\n    return bool(result)","typeGuard":"def has_text_content(result) -> bool:\n    import mcp.types as mcp_types\n    return bool(result) and isinstance(result[0], mcp_types.TextResourceContents)","tryCatchPattern":"try:\n    manifest = await get_skill_manifest(client, skill_name)\nexcept ValueError as e:\n    if \"Could not read manifest\" in str(e):\n        raise SkillNotFoundError(skill_name) from e\n    raise","preventionTips":["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."],"tags":["skills","mcp-resources","manifest"],"backgroundTag":"empty-resource-response","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}