PrefectHQ/fastmcp · error · ValueError
Invalid manifest format for skill: {skill_name}
Error message
Invalid manifest format for skill: {skill_name} What it means
The manifest parsed as JSON but its structure didn't match `SkillManifest` — required keys (`skill`, `files` with `path`/`size`/`hash`) were missing or of the wrong type, so the KeyError/TypeError from dict/field access is re-raised as this ValueError. The JSON is valid but the manifest shape is wrong.
Source
Thrown at fastmcp_slim/fastmcp/utilities/skills.py:124
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"]
],
)
except (KeyError, TypeError) as e:
raise ValueError(f"Invalid manifest format for skill: {skill_name}") from e
async def download_skill(
client: Client,
skill_name: str,
target_dir: str | Path,
*,
overwrite: bool = False,
) -> Path:
"""Download a skill and all its files to a local directory.
Creates a subdirectory named after the skill containing all files.
Args:
client: Connected FastMCP client
skill_name: Name of the skill to download
target_dir: Directory where skill folder will be created
overwrite: If True, overwrite existing skill directory. If FalseView on GitHub (pinned to 1f02114297)
Solutions
- Dump the raw manifest JSON and compare against the expected shape: `{"skill": <name>, "files": [{"path", "size", "hash"}, ...]}`.
- Update or fix the skill server to emit all required fields with correct types.
- Align server and client FastMCP versions if the manifest schema changed between releases.
Example fix
// before
{"skill": "my-skill", "files": ["a.py", "b.py"]}
// after
{"skill": "my-skill", "files": [{"path": "a.py", "size": 100, "hash": "sha256:..."}]} Defensive patterns
Strategy: validation
Validate before calling
def manifest_shape_ok(manifest: dict) -> bool:
if not isinstance(manifest, dict) or "skill" not in manifest or "files" not in manifest:
return False
files = manifest["files"]
if not isinstance(files, list):
return False
return all(
isinstance(f, dict)
and isinstance(f.get("path"), str)
and isinstance(f.get("size"), int)
and isinstance(f.get("hash"), str)
for f in files
) Type guard
import json
import mcp.types as mcp_types
def parse_valid_manifest(text: str) -> dict | None:
try:
data = json.loads(text)
except json.JSONDecodeError:
return None
if manifest_shape_ok(data):
return data
return None Try / catch
try:
manifest = await get_skill_manifest(client, skill_name)
except ValueError as e:
if "Invalid manifest format" in str(e):
raw = json.loads((await client.read_resource(f"skill://{skill_name}/_manifest"))[0].text)
logger.error("Manifest shape mismatch for %s: keys=%s", skill_name, list(raw))
raise Prevention
- Keep skill-server manifest output aligned with FastMCP's SkillManifest schema (skill, files[path/size/hash]).
- Pin compatible FastMCP versions on server and client if the manifest format changes.
- Validate manifests with a JSON schema in the server's own test suite.
When it happens
Trigger: A skill server emits manifest JSON that lacks the `skill` or `files` keys, whose `files` entries are missing `path`, `size`, or `hash`, or where `files` is not a list of objects (e.g. a dict or list of strings).
Common situations: Version drift between the skill server's manifest format and what FastMCP expects, hand-written or third-party manifests that don't follow the schema, partial manifests produced when file metadata generation failed.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Could not read manifest for skill: {skill_name}
- Invalid manifest JSON for skill: {skill_name}
- Invalid CIMD document: {e}
- Elicitation schema must be an object schema, got type '{sche
- Elicitation schema field '{prop_name}' has type '{prop_type}
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/c0e61264560d0aad.
Report an issue: GitHub.