{"record":{"id":"2b6e0f14d264e910","repo":"PrefectHQ/fastmcp","slug":"invalid-manifest-json-for-skill-skill-name","errorCode":null,"errorMessage":"Invalid manifest JSON for skill: {skill_name}","messagePattern":"Invalid manifest JSON for skill: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/utilities/skills.py","lineNumber":111,"sourceCode":"\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        )\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,","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/utilities/skills.py#L93-L129","documentation":"The manifest resource came back as text content, but `json.loads` failed to parse it, so `get_skill_manifest` re-raises as this ValueError with the JSONDecodeError chained. The server returned something that should be manifest JSON but isn't valid JSON.","triggerScenarios":"A skill server whose `_manifest` resource emits malformed JSON — truncated output, an error page/markup served as text, YAML instead of JSON, or debug/log text accidentally written into the manifest resource.","commonSituations":"Custom or third-party skill servers with broken manifest generation, server-side template errors rendering into the resource body, encoding issues corrupting the payload, or an outdated server whose manifest format changed.","solutions":["Fetch the raw `_manifest` resource yourself (e.g. `await client.read_resource(f\"skill://{name}/_manifest\")`) and inspect the text to see exactly what the server returned.","Fix or update the skill server so the manifest resource emits valid JSON matching the SkillManifest shape.","Check the server logs for errors occurring during manifest serialization."],"exampleFix":"// before (server side)\nreturn \"name: my-skill\"  # YAML, not JSON\n// after\nreturn json.dumps({\"skill\": \"my-skill\", \"files\": []})","handlingStrategy":"try-catch","validationCode":"import json\nasync def manifest_is_valid_json(client, skill_name: str) -> bool:\n    import mcp.types as mcp_types\n    result = await client.read_resource(f\"skill://{skill_name}/_manifest\")\n    if not result or not isinstance(result[0], mcp_types.TextResourceContents):\n        return False\n    try:\n        json.loads(result[0].text)\n        return True\n    except json.JSONDecodeError:\n        return False","typeGuard":"import json\nimport mcp.types as mcp_types\n\ndef is_text_json_content(item: object) -> bool:\n    if not isinstance(item, mcp_types.TextResourceContents):\n        return False\n    try:\n        json.loads(item.text)\n        return True\n    except json.JSONDecodeError:\n        return False","tryCatchPattern":"try:\n    manifest = await get_skill_manifest(client, skill_name)\nexcept ValueError as e:\n    if \"Invalid manifest JSON\" in str(e):\n        raw = (await client.read_resource(f\"skill://{skill_name}/_manifest\"))[0].text\n        logger.error(\"Bad manifest payload from server: %.200s\", raw)\n    raise","preventionTips":["Fix skill servers to emit valid JSON (never YAML or template output) for `_manifest`.","Check server logs for serialization errors when the manifest is generated.","Add a smoke test that reads the manifest and json.loads it in CI."],"tags":["skills","json","manifest"],"backgroundTag":"invalid-json-payload","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}