diff --git a/graphene/relay/node.py b/graphene/relay/node.py index 571f8b5c..f8927ab7 100644 --- a/graphene/relay/node.py +++ b/graphene/relay/node.py @@ -90,13 +90,25 @@ class Node(AbstractNode): def get_node_from_global_id(cls, info, global_id, only_type=None): try: _type, _id = cls.from_global_id(global_id) - graphene_type = info.schema.get_type(_type).graphene_type except Exception as e: raise Exception( - "Unable to call from_global_id, is the id a base64 encoding of 'TypeName:id': {} Exception: {}".format( - str(global_id), str(e) + ( + 'Unable to parse global ID "{global_id}". ' + 'Make sure it is a base64 encoded string in the format: "TypeName:id". ' + "Exception message: {exception}".format( + global_id=global_id, exception=str(e) + ) ) ) + + graphene_type = info.schema.get_type(_type) + if graphene_type is None: + raise Exception( + 'Relay Node "{_type}" not found in schema'.format(_type=_type) + ) + + graphene_type = graphene_type.graphene_type + if only_type: assert graphene_type == only_type, ("Must receive a {} id.").format( only_type._meta.name @@ -104,7 +116,11 @@ class Node(AbstractNode): # We make sure the ObjectType implements the "Node" interface if cls not in graphene_type._meta.interfaces: - return None + raise Exception( + 'ObjectType "{_type}" does not implement the "{cls}" interface.'.format( + _type=_type, cls=cls + ) + ) get_node = getattr(graphene_type, "get_node", None) if get_node: diff --git a/graphene/relay/tests/test_node.py b/graphene/relay/tests/test_node.py index 279b930e..de1802e9 100644 --- a/graphene/relay/tests/test_node.py +++ b/graphene/relay/tests/test_node.py @@ -1,3 +1,4 @@ +import re from graphql_relay import to_global_id from graphql.pyutils import dedent @@ -83,6 +84,20 @@ def test_node_requesting_non_node(): executed = schema.execute( '{ node(id:"%s") { __typename } } ' % Node.to_global_id("RootQuery", 1) ) + assert executed.errors + assert re.match( + r"ObjectType .* does not implement the .* interface.", + executed.errors[0].message, + ) + assert executed.data == {"node": None} + + +def test_node_requesting_unknown_type(): + executed = schema.execute( + '{ node(id:"%s") { __typename } } ' % Node.to_global_id("UnknownType", 1) + ) + assert executed.errors + assert re.match(r"Relay Node .* not found in schema", executed.errors[0].message) assert executed.data == {"node": None} @@ -91,6 +106,7 @@ def test_node_query_incorrect_id(): '{ node(id:"%s") { ... on MyNode { name } } }' % "something:2" ) assert executed.errors + assert re.match(r"Unable to parse global ID .*", executed.errors[0].message) assert executed.data == {"node": None}