{"record":{"id":"98acbcc81f3b8346","repo":"PrefectHQ/fastmcp","slug":"meta-fastmcp-must-be-a-dict","errorCode":null,"errorMessage":"meta['fastmcp'] must be a dict","messagePattern":"meta\\['fastmcp'\\] must be a dict","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/utilities/components.py","lineNumber":179,"sourceCode":"    def get_meta(self) -> dict[str, Any]:\n        \"\"\"Get the meta information about the component.\n\n        Returns a dict that always includes a `fastmcp` key containing:\n        - `tags`: sorted list of component tags\n        - `version`: component version (only if set)\n\n        Internal keys (prefixed with `_`) are stripped from the fastmcp namespace.\n        \"\"\"\n        meta = dict(self.meta) if self.meta else {}\n\n        fastmcp_meta: FastMCPMeta = {\"tags\": sorted(self.tags)}\n        if self.version is not None:\n            fastmcp_meta[\"version\"] = self.version\n\n        # Merge with upstream fastmcp meta, stripping internal keys\n        if (upstream_meta := meta.get(\"fastmcp\")) is not None:\n            if not isinstance(upstream_meta, dict):\n                raise TypeError(\"meta['fastmcp'] must be a dict\")\n            # Filter out internal keys (e.g., _internal used for enabled state)\n            public_upstream = {\n                k: v for k, v in upstream_meta.items() if not k.startswith(\"_\")\n            }\n            fastmcp_meta = cast(FastMCPMeta, public_upstream | fastmcp_meta)\n        meta[\"fastmcp\"] = fastmcp_meta\n\n        return meta\n\n    def __eq__(self, other: object) -> bool:\n        if type(self) is not type(other):\n            return False\n        if not isinstance(other, type(self)):\n            return False\n        return self.model_dump() == other.model_dump()\n\n    def __repr__(self) -> str:\n        parts = [f\"name={self.name!r}\"]","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/utilities/components.py#L161-L197","documentation":"`get_meta` merges the component's upstream `meta['fastmcp']` dict with FastMCP-generated metadata (key, version, tags, etc.). If a user supplies `meta={'fastmcp': <non-dict>}`, the merge is impossible and a TypeError is raised. This validates the reserved 'fastmcp' meta namespace before internal keys are stripped.","triggerScenarios":"Constructing any FastMCP component with `meta={'fastmcp': 'text'}` or any non-dict value (string, list, int, None-adjacent garbage).","commonSituations":"Typos like `meta={'fastmcp': True}`; misunderstanding that the 'fastmcp' meta key is reserved and must be a mapping; programmatically built meta from JSON where the value lost its shape.","solutions":["Ensure `meta['fastmcp']` is a dict, e.g. `meta={'fastmcp': {'team': 'platform'}}`.","Remove the 'fastmcp' key if you did not intend to customize FastMCP metadata.","Validate meta structure before passing it to constructors/decorators."],"exampleFix":"// before\n@mcp.tool(meta={'fastmcp': 'owner:alice'})\n// after\n@mcp.tool(meta={'fastmcp': {'owner': 'alice'}})","handlingStrategy":"validation","validationCode":"def check_meta(meta):\n    if meta and 'fastmcp' in meta and not isinstance(meta['fastmcp'], dict):\n        raise TypeError(\"meta['fastmcp'] must be a dict\")","typeGuard":"from typing import TypedDict, cast\ndef is_fastmcp_meta(meta) -> bool:\n    return isinstance(meta, dict) and isinstance(meta.get('fastmcp'), (dict, type(None)))","tryCatchPattern":"try:\n    result = component.get_meta()\nexcept TypeError:\n    meta['fastmcp'] = {}\n    result = component.get_meta()","preventionTips":["Treat the 'fastmcp' meta key as reserved and always dict-shaped","Validate meta dicts parsed from JSON before passing to constructors","Document custom metadata under non-reserved top-level keys"],"tags":["fastmcp","validation","metadata","type-error"],"backgroundTag":"invalid-meta-type","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}