Repository: strawberry-graphql/strawberry

Issue:
GlobalID#resolve_type does not handle invalid IDs
<!-- Provide a general summary of the bug in the title above. -->

<!--- This template is entirely optional and can be removed, but is here to help both you and us. -->
<!--- Anything on lines wrapped in comments like these will not show up in the final text. -->

## Describe the Bug
`GlobalID#resolve_type` asserts that the resolved type is a `StrawberryObjectDefinition` and is a subclass of `Node`. However the Global ID is usually provided _by the user_, so an invalid ID will trigger this assertion (because there is no such type or the type is not a relay Node) and result in a bogus error response to the client. Instead such an ID should be handled just like a normal "not found".

<!-- A clear and concise description of what the bug is. -->

## System Information

 - Operating system: Ubuntu
 - Strawberry version (if applicable): 0.234.0


<!-- POLAR PLEDGE BADGE START -->
## Upvote & Fund

- We're using [Polar.sh](https://polar.sh/strawberry-graphql) so you can upvote and help fund this issue.
- We receive the funding once the issue is completed & confirmed by you.
- Thank you in advance for helping prioritize & fund our backlog.

<a href="https://polar.sh/strawberry-graphql/strawberry/issues/3532">
<picture>
  <source media="(prefers-color-scheme: dark)" srcset="https://polar.sh/api/github/strawberry-graphql/strawberry/issues/3532/pledge.svg?darkmode=1">
  <img alt="Fund with Polar" src="https://polar.sh/api/github/strawberry-graphql/strawberry/issues/3532/pledge.svg">
</picture>
</a>
<!-- POLAR PLEDGE BADGE END -->



Discussion:
@diesieben07 can you share a reproduction? :D 

Thanks 😊
Here you go: https://play.strawberry.rocks/?gist=feaeb32b37ac52cadf807ad4b24b483a
Note the ID being passed decodes to `�erson:1` (I intentionally changed the first character of the correct Base64 for `Person:1`).
When passing `UGVyc29uOjI=` ("Person:2") you get the correct response: null.

Resolving patch:
diff --git a/strawberry/relay/types.py b/strawberry/relay/types.py
--- a/strawberry/relay/types.py
+++ b/strawberry/relay/types.py
@@ -220,14 +220,22 @@ def resolve_type(self, info: Info) -> Type[Node]:
 
         """
         type_def = info.schema.get_type_by_name(self.type_name)
-        assert isinstance(type_def, StrawberryObjectDefinition)
+        if not isinstance(type_def, StrawberryObjectDefinition):
+            raise GlobalIDValueError(
+                f"Cannot resolve. GlobalID requires a GraphQL type, "
+                f"received `{self.type_name}`."
+            )
 
         origin = (
             type_def.origin.resolve_type
             if isinstance(type_def.origin, LazyType)
             else type_def.origin
         )
-        assert issubclass(origin, Node)
+        if not issubclass(origin, Node):
+            raise GlobalIDValueError(
+                f"Cannot resolve. GlobalID requires a GraphQL Node type, "
+                f"received `{self.type_name}`."
+            )
         return origin
 
     @overload


Test patch:
diff --git a/tests/relay/test_exceptions.py b/tests/relay/test_exceptions.py
--- a/tests/relay/test_exceptions.py
+++ b/tests/relay/test_exceptions.py
@@ -3,7 +3,8 @@
 import pytest
 
 import strawberry
-from strawberry import relay
+from strawberry import Info, relay
+from strawberry.relay import GlobalID
 from strawberry.relay.exceptions import (
     NodeIDAnnotationError,
     RelayWrongAnnotationError,
@@ -16,6 +17,52 @@ class NonNodeType:
     foo: str
 
 
+def test_raises_error_on_unknown_node_type_in_global_id():
+    @strawberry.type
+    class Query:
+        @strawberry.field()
+        def test(self, info: Info) -> GlobalID:
+            _id = GlobalID("foo", "bar")
+            _id.resolve_type(info)
+            return _id
+
+    schema = strawberry.Schema(query=Query)
+
+    result = schema.execute_sync("""
+        query TestQuery {
+            test
+        }
+    """)
+    assert len(result.errors) == 1
+    assert (
+        result.errors[0].message
+        == "Cannot resolve. GlobalID requires a GraphQL type, received `foo`."
+    )
+
+
+def test_raises_error_on_non_node_type_in_global_id():
+    @strawberry.type
+    class Query:
+        @strawberry.field()
+        def test(self, info: Info) -> GlobalID:
+            _id = GlobalID("NonNodeType", "bar")
+            _id.resolve_type(info)
+            return _id
+
+    schema = strawberry.Schema(query=Query, types=(NonNodeType,))
+
+    result = schema.execute_sync("""
+        query TestQuery {
+            test
+        }
+    """)
+    assert len(result.errors) == 1
+    assert (
+        result.errors[0].message == "Cannot resolve. GlobalID requires a GraphQL Node "
+        "type, received `NonNodeType`."
+    )
+
+
 @pytest.mark.raises_strawberry_exception(
     NodeIDAnnotationError,
     match='No field annotated with `NodeID` found in "Fruit"',