{"record":{"id":"9cb87c7cce33de06","repo":"PrefectHQ/fastmcp","slug":"contents-must-be-str-bytes-or-list-resourceconte","errorCode":null,"errorMessage":"contents must be str, bytes, or list[ResourceContent], got {type(contents).__name__}","messagePattern":"contents must be str, bytes, or list\\[ResourceContent\\], got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/resources/base.py","lineNumber":193,"sourceCode":"            return [ResourceContent(contents)]\n        if isinstance(contents, bytes):\n            return [ResourceContent(contents)]\n        if isinstance(contents, list):\n            # Validate all items are ResourceContent\n            for i, item in enumerate(contents):\n                if not isinstance(item, ResourceContent):\n                    raise TypeError(\n                        f\"contents[{i}] must be ResourceContent, got {type(item).__name__}. \"\n                        f\"Use ResourceContent({item!r}) to wrap the value.\"\n                    )\n            return contents\n        # Auto-serialize JSON-native types to JSON text\n        if (\n            isinstance(contents, dict | list | tuple | int | float | bool)\n            or contents is None\n        ):\n            return [ResourceContent(json.dumps(contents), mime_type=\"application/json\")]\n        raise TypeError(\n            f\"contents must be str, bytes, or list[ResourceContent], got {type(contents).__name__}\"\n        )\n\n    def to_mcp_result(self, uri: AnyUrl | str) -> mcp_types.ReadResourceResult:\n        \"\"\"Convert to MCP ReadResourceResult.\n\n        Args:\n            uri: The URI of the resource (required by MCP types)\n\n        Returns:\n            MCP ReadResourceResult with converted contents\n        \"\"\"\n        mcp_contents = [item.to_mcp_resource_contents(uri) for item in self.contents]\n        return mcp_types.ReadResourceResult(\n            contents=mcp_contents,\n            _meta=self.meta,  # type: ignore[call-arg]  # _meta is Pydantic alias for meta field\n        )\n","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/resources/base.py#L175-L211","documentation":"ResourceResult._normalize_contents only understands str, bytes, list[ResourceContent], and JSON-native scalars/containers (dict, list, tuple, int, float, bool, None). Anything else — a custom object, a set, a datetime, a generator — falls through to this TypeError because the library cannot know how to serialize it.","triggerScenarios":"ResourceResult(contents=some_object); ResourceResult(contents={1,2}); ResourceResult(contents=datetime.now()); ResourceResult(contents=(x for x in items)) — any non-str/bytes/list/JSON-native value passed as contents to ResourceResult.__init__.","commonSituations":"Returning ORM model instances, dataclasses, Decimal, sets, or generators from resource functions; forgetting to json.dumps or str() custom objects before wrapping.","solutions":["Convert the value first: json.dumps(value, default=str) wrapped in ResourceContent, or str(value)","Serialize dataclasses/Pydantic models with model_dump()/asdict() before passing","If it's binary, pass bytes directly"],"exampleFix":"// before\nreturn ResourceResult(contents=my_dataclass_instance)\n// after\nreturn ResourceResult(contents=json.dumps(asdict(my_dataclass_instance), default=str), meta=None)\n// or rely on auto-serialization for JSON-native values:\nreturn ResourceResult(contents=my_dataclass_instance.__dict__)","handlingStrategy":"validation","validationCode":"JSON_NATIVE = (dict, list, tuple, int, float, bool)\ndef ok(contents):\n    return isinstance(contents, (str, bytes)) or isinstance(contents, JSON_NATIVE) or contents is None\nassert ok(payload), f\"unsupported contents type: {type(payload).__name__}\"","typeGuard":"def is_serializable_contents(c) -> bool:\n    return isinstance(c, (str, bytes, dict, list, tuple, int, float, bool)) or c is None","tryCatchPattern":"try:\n    return ResourceResult(contents=value)\nexcept TypeError:\n    return ResourceResult(contents=json.dumps(value, default=str))","preventionTips":["Serialize custom objects (dataclasses, models, Decimal, sets) before passing contents","Use json.dumps(..., default=str) for anything not JSON-native","Avoid returning generators or ORM objects from resource functions"],"tags":["python","resources","type-error"],"backgroundTag":"unsupported-type-serialization","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}