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 False

View on GitHub (pinned to 1f02114297)

Solutions

  1. Dump the raw manifest JSON and compare against the expected shape: `{"skill": <name>, "files": [{"path", "size", "hash"}, ...]}`.
  2. Update or fix the skill server to emit all required fields with correct types.
  3. 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

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


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/c0e61264560d0aad. Report an issue: GitHub.