{"record":{"id":"e24c5fa02658110c","repo":"PrefectHQ/fastmcp","slug":"unexpected-manifest-format-for-skill-skill-name","errorCode":null,"errorMessage":"Unexpected manifest format for skill: {skill_name}","messagePattern":"Unexpected manifest format for skill: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/utilities/skills.py","lineNumber":113,"sourceCode":"        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        )\n    except (KeyError, TypeError) as e:\n        raise ValueError(f\"Invalid manifest format for skill: {skill_name}\") from e\n\n\nasync def download_skill(\n    client: Client,\n    skill_name: str,\n    target_dir: str | Path,\n    *,","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/utilities/skills.py#L95-L131","documentation":"`get_skill_manifest` expects the manifest resource's first content item to be `TextResourceContents`; when the server returns a different content type (e.g. BlobResourceContents/binary), this ValueError is raised because the manifest cannot be interpreted as JSON text.","triggerScenarios":"Calling `get_skill_manifest` against a skill server that serves the `_manifest` resource as a binary blob or otherwise non-text content rather than `TextResourceContents`.","commonSituations":"Custom skill-server implementations that base64-encode or otherwise blob-encode the manifest, middleware that converts text resources to blobs, or a server bug registering the manifest under a mime type that triggers blob handling.","solutions":["Fix the skill server so `_manifest` is registered as a text resource (application/json TextResourceContents).","Inspect what content type the server returns for `skill://{name}/_manifest` and correct the resource registration/mime type.","If a proxy is involved, ensure it isn't rewriting resource contents into blobs."],"exampleFix":"// before (server side)\nyield BlobResourceContents(uri=uri, blob=base64.b64encode(data))\n// after\nyield TextResourceContents(uri=uri, mimeType=\"application/json\", text=json.dumps(manifest))","handlingStrategy":"type-guard","validationCode":"import mcp.types as mcp_types\nasync def manifest_content_type(client, skill_name: str) -> str | None:\n    result = await client.read_resource(f\"skill://{skill_name}/_manifest\")\n    if result and isinstance(result[0], mcp_types.TextResourceContents):\n        return result[0].mimeType\n    return None","typeGuard":"import mcp.types as mcp_types\n\ndef is_text_resource_content(item: object) -> bool:\n    return isinstance(item, mcp_types.TextResourceContents)","tryCatchPattern":"try:\n    manifest = await get_skill_manifest(client, skill_name)\nexcept ValueError as e:\n    if \"Unexpected manifest format\" in str(e):\n        raise SkillServerMisconfigured(\n            f\"{skill_name}: server returns non-text manifest; register it as TextResourceContents\"\n        ) from e\n    raise","preventionTips":["Register the `_manifest` resource as text with mimeType application/json.","Ensure proxies/middleware don't convert text resources to blobs.","Assert the content type in integration tests for custom skill servers."],"tags":["skills","mcp-resources","content-type"],"backgroundTag":"unexpected-content-type","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}