Relay library for graphql-core
raw JSON → 3.2.0 verified Tue May 12 auth: no python install: verified quickstart: stale
graphql-relay-py is the Python port of the JavaScript Relay library for GraphQL, designed to facilitate the creation of Relay-compliant GraphQL servers using graphql-core. It provides utilities for global object identification (Nodes) and cursor-based pagination (Connections). The library maintains a regular release cadence, often aligning with updates to graphql-core and the upstream graphql-relay-js specification. The current version is 3.2.0.
pip install graphql-relay graphql-core Common errors
error ModuleNotFoundError: No module named 'graphql' ↓
cause The 'graphql-core' library, a core dependency for 'graphql-relay', is not installed in the Python environment, or there's an issue with the Python path.
fix
Ensure 'graphql-core' is installed:
pip install graphql-core. error AttributeError: 'NoneType' object has no attribute '...' ↓
cause This often occurs in a Relay context when a resolver (e.g., within `node_definitions` or for a field derived from `global_id_field`) returns `None` where a GraphQL type expects a non-null object, or when `from_global_id` cannot resolve a valid object.
fix
Check the resolver functions (especially the
get_node_from_global_id function passed to node_definitions) to ensure they correctly retrieve and return the expected object for a given ID, and that all necessary data is available and not None before attempting to access its attributes. error RelayResponseNormalizer: Invalid record '...'. Expected __typename to be consistent, but the record was assigned conflicting types Foo and Bar. The GraphQL server likely violated the globally unique ID requirement by returning the same ID for different objects. ↓
cause This client-side Relay error indicates that the GraphQL server is returning the same global ID for two different types of objects, violating Relay's requirement for globally unique IDs across all types.
fix
Ensure that the
to_global_id and from_global_id functions (or their equivalents if manually implemented) correctly generate unique IDs by incorporating both the type name and the object's local ID, preventing collisions between different types that might share the same local ID values. error Error: "Node" expects field "id" (or similar: Disallowed type `String` of field `id` on parent type `Foo` cannot be used by Relay to identify entities.) ↓
cause A GraphQL type that implements the Relay `Node` interface has an `id` field defined with an incorrect type (e.g., `String` instead of `ID!`) or the `global_id_field` is not properly used to expose the `id` field as a globally unique identifier.
fix
Define the
id field on types implementing Node using graphql_relay.global_id_field() and ensure it correctly maps to the object's unique identifier. The id field should always have the ID! GraphQL type. error TypeError: (0 , _graphql.resolveObjMapThunk) is not a function ↓
cause This error typically points to an incompatibility between the installed versions of `graphql-relay` and `graphql-core`, where a function signature or module export has changed between versions, especially when upgrading one library without the other.
fix
Ensure that
graphql-relay and graphql-core are compatible versions. Often, updating both libraries to their latest compatible versions (pip install --upgrade graphql-relay graphql-core) resolves such issues. Warnings
breaking Version 3.0.0 introduced significant breaking changes to align with graphql-core version 3.x. Code written for graphql-relay-py v2.x (compatible with graphql-core v2.x) will not work with v3.x without migration. ↓
fix Migrate your graphql-core dependency to v3.x and update your graphql-relay-py imports and API calls as necessary. Review the graphql-core and graphql-relay-py v3 release notes for specific changes. This also requires Python 3.6+.
breaking Versions 2.0.0 and 0.5.0 introduced breaking changes relating to compatibility with specific major versions of `graphql-core`. `v2.0.0` was compatible with `graphql-core < 3`, and `v0.5.0` with `graphql-core < 2`. ↓
fix Ensure that your `graphql-relay-py` version matches the expected `graphql-core` major version. For new projects, use `graphql-relay-py` v3.x with `graphql-core` v3.x.
gotcha The internal `arrayconnection` module was temporarily renamed to `array_connection` in `v3.1.1` as part of a `snake_case` consistency drive, which could break direct imports. It was later re-added for backward compatibility in `v3.1.5`. ↓
fix For new code, prefer importing connection-related utilities like `connection_from_array` directly from the top-level `graphql_relay` package. If you must use `arrayconnection`, ensure your version is `3.1.5` or later, or adapt to `array_connection` if on affected versions.
gotcha The behavior of `unbase64` changed in `v3.1.2` to return an empty string on errors instead of potentially raising an exception, and `from_global_id` behavior was adjusted in `v3.1.3` to match `relay-js`. ↓
fix Update your code to handle `unbase64` returning an empty string for invalid inputs if you were previously relying on exceptions for error handling. Review `from_global_id` usage, especially if parsing IDs from external sources.
breaking The 'graphene' package is a core dependency and must be installed. This error occurs when 'graphene' is not found in the Python environment. ↓
fix Ensure 'graphene' is installed in your Python environment, e.g., by running `pip install graphene`.
breaking The 'graphene' package was not found. This indicates that `graphene` is not installed in the environment where the script is being executed. ↓
fix Ensure that the `graphene` package is installed in your environment. You can typically install it using `pip install graphene`.
Install compatibility verified last tested: 2026-05-12
python os / libc status wheel install import disk
3.10 alpine (musl) wheel - 0.21s 19.9M
3.10 alpine (musl) - - 0.22s 19.9M
3.10 slim (glibc) wheel 1.7s 0.15s 20M
3.10 slim (glibc) - - 0.14s 20M
3.11 alpine (musl) wheel - 0.33s 22.1M
3.11 alpine (musl) - - 0.36s 22.1M
3.11 slim (glibc) wheel 1.8s 0.29s 23M
3.11 slim (glibc) - - 0.46s 23M
3.12 alpine (musl) wheel - 0.54s 13.9M
3.12 alpine (musl) - - 0.56s 13.9M
3.12 slim (glibc) wheel 1.6s 0.54s 14M
3.12 slim (glibc) - - 0.50s 14M
3.13 alpine (musl) wheel - 0.53s 13.6M
3.13 alpine (musl) - - 0.56s 13.5M
3.13 slim (glibc) wheel 1.6s 0.48s 14M
3.13 slim (glibc) - - 0.51s 14M
3.9 alpine (musl) wheel - 0.19s 19.7M
3.9 alpine (musl) - - 0.21s 19.7M
3.9 slim (glibc) wheel 2.1s 0.20s 20M
3.9 slim (glibc) - - 0.18s 20M
Imports
- connection_args
from graphql_relay import connection_args - connection_definitions
from graphql_relay import connection_definitions - connection_from_array
from graphql_relay import connection_from_array - from_global_id
from graphql_relay import from_global_id - to_global_id
from graphql_relay import to_global_id - global_id_field
from graphql_relay import global_id_field - node_definitions
from graphql_relay import node_definitions - arrayconnection wrong
from graphql_relay.connection.arrayconnection import connection_from_arraycorrectfrom graphql_relay.connection.arrayconnection import connection_from_array_slice
Quickstart stale last tested: 2026-04-24
import graphene
from graphql.execution.execute import execute
from graphql.language.parser import parse
from graphql_relay import node_definitions, global_id_field, connection_definitions, connection_from_array, connection_args, from_global_id
class User:
def __init__(self, id, name):
self.id = id
self.name = name
users_data = {
"1": User("1", "Alice"),
"2": User("2", "Bob"),
}
def get_user(id):
return users_data.get(id)
def get_object_from_global_id(global_id, info):
type_name, id = from_global_id(global_id)
if type_name == 'User':
return get_user(id)
return None
node_interface, node_field = node_definitions(
get_object_from_global_id, lambda obj, info: UserNode if isinstance(obj, User) else None
)
class UserNode(graphene.ObjectType):
class Meta:
name = 'User'
interfaces = (node_interface,)
id = global_id_field('User')
name = graphene.String()
UserConnection = connection_definitions(UserNode, 'UserConnection').connection_type
class Query(graphene.ObjectType):
node = node_field
users = graphene.Field(
UserConnection,
args=connection_args,
resolve=lambda obj, info, **args:
connection_from_array(list(users_data.values()), args)
)
schema = graphene.Schema(query=Query)
# Example Usage:
query_str = '''
query {
users (first: 1) {
edges {
node {
id
name
}
}
}
node(id: "VXNlcjox") {
id
... on User {
name
}
}
}
'''
# Assuming "VXNlcjox" is the global ID for User:1 (to_global_id('User', '1'))
# Use 'User:1' -> base64 -> 'VXNlcjox'
result = execute(schema, parse(query_str))
print(result.data)