{"record":{"id":"bd13c1ed5189ab8d","repo":"PrefectHQ/fastmcp","slug":"either-name-or-uri-must-be-provided","errorCode":null,"errorMessage":"Either name or uri must be provided","messagePattern":"Either name or uri must be provided","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/resources/base.py","lineNumber":410,"sourceCode":"        )\n\n    @field_validator(\"mime_type\", mode=\"before\")\n    @classmethod\n    def set_default_mime_type(cls, mime_type: str | None) -> str:\n        \"\"\"Set default MIME type if not provided.\"\"\"\n        if mime_type:\n            return mime_type\n        return \"text/plain\"\n\n    @model_validator(mode=\"after\")\n    def set_default_name(self) -> Self:\n        \"\"\"Set default name from URI if not provided.\"\"\"\n        if self.name:\n            pass\n        elif self.uri:\n            self.name = str(self.uri)\n        else:\n            raise ValueError(\"Either name or uri must be provided\")\n        return self\n\n    async def read(\n        self,\n    ) -> str | bytes | ResourceResult:\n        \"\"\"Read the resource content.\n\n        Subclasses implement this to return resource data. Supported return types:\n            - str: Text content\n            - bytes: Binary content\n            - ResourceResult: Full control over contents and result-level meta\n        \"\"\"\n        raise NotImplementedError(\"Subclasses must implement read()\")\n\n    def convert_result(self, raw_value: Any) -> ResourceResult:\n        \"\"\"Convert a raw result to ResourceResult.\n\n        This is used in two contexts:","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/resources/base.py#L392-L428","documentation":"Resource.set_default_name derives the resource name from its URI when no explicit name was given. If neither name nor uri is set, there is nothing to derive from and it raises this ValueError. It is a configuration-completeness check ensuring every resource has an MCP-visible identity.","triggerScenarios":"Calling set_default_name() on a Resource constructed with neither name= nor uri= (or with empty-string name and no uri).","commonSituations":"Building resources programmatically and forgetting to pass uri; name accidentally set to \"\" which is falsy so the elif falls through to uri, which is also unset.","solutions":["Pass a uri when constructing the Resource (e.g. Resource(uri='file:///data', ...) or via FunctionResource)","Or pass an explicit name= so derivation is unnecessary","Check for empty-string name values, which are falsy and don't count"],"exampleFix":"// before\nres = Resource(fn=read_fn)\nres.set_default_name()  # ValueError\n// after\nres = Resource(fn=read_fn, uri=\"data://config\")\nres.set_default_name()  # name becomes \"data://config\"","handlingStrategy":"validation","validationCode":"def ensure_identity(name, uri):\n    if not name and not uri:\n        raise ValueError(\"Provide name or uri before set_default_name()\")","typeGuard":"def has_identity(res) -> bool:\n    return bool(getattr(res, \"name\", None)) or bool(getattr(res, \"uri\", None))","tryCatchPattern":"try:\n    res.set_default_name()\nexcept ValueError:\n    res.name = res.uri = \"data://fallback\"\n    res.set_default_name()","preventionTips":["Always pass uri= when constructing Resource objects programmatically","Remember empty-string name is falsy and does not satisfy the check","Validate resource definitions at startup, not first read"],"tags":["python","resources","value-error"],"backgroundTag":"missing-required-identifier","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}