Troubleshooting

This guide covers common issues encountered when using Strawberry Django and their solutions.

Installation and Setup Issues

Module Not Found

Problem: ModuleNotFoundError: No module named 'strawberry_django'

Solution: Ensure the package is installed:

Terminal window
pip install strawberry-graphql-django

Type and Field Resolution

Auto Type Resolution Fails

Problem: strawberry.auto doesn’t resolve the correct type.

Solution: Define custom type mapping for non-standard Django fields:

from strawberry_django.fields.types import field_type_map
from django.db import models
import strawberry
# Map custom Django field to GraphQL type
field_type_map.update({
models.SlugField: str,
models.JSONField: strawberry.scalars.JSON,
})

See Fields - Defining types for auto fields for more details.

Forward Reference Errors

Problem: NameError: name 'SomeType' is not defined

Solution: Use string annotations for forward references:

@strawberry_django.type(models.Author)
class Author:
id: auto
name: auto
books: list["Book"] # String reference, not Book
@strawberry_django.type(models.Book)
class Book:
id: auto
title: auto
author: "Author" # String reference

Type Annotation Issues with Ordering

Problem: TypeError: unsupported operand type(s) for |: 'str' and 'NoneType'

Solution: This occurs with self-referential ordering in Python 3.13+. Use Optional or proper forward references:

from typing import Optional
@strawberry_django.order_type(models.User)
class UserOrder:
name: auto
# ❌ creator: "UserOrder" # Fails in Python 3.13+
creator: Optional["UserOrder"] = None # βœ… Works

Query Optimization

N+1 Query Problems

Problem: Multiple database queries are executed for related objects.

Solution 1: Enable the Query Optimizer Extension (recommended):

schema.py
from strawberry_django.optimizer import DjangoOptimizerExtension
schema = strawberry.Schema(
query=Query,
extensions=[DjangoOptimizerExtension],
)

Solution 2: Use DataLoaders for custom batching:

See DataLoaders guide for details.

Solution 3: Add optimization hints to model properties:

from strawberry_django.descriptors import model_property
@model_property(select_related=["author"], only=["author__name"])
def author_name(self) -> str:
return self.author.name

Annotated Fields Not Working in Nested Queries

Problem: Annotations defined with strawberry_django.field(annotate=...) don’t work in nested queries.

Cause: The optimizer may not apply annotations correctly in deeply nested contexts.

Solution: Use model-level annotations or custom DataLoaders:

from django.db.models import Count
from strawberry_django.descriptors import model_property
@model_property(
annotate={"_book_count": Count("books")}
)
def book_count(self) -> int:
return self._book_count # type: ignore

Deferred Field Access Issues

Problem: Accessing a field triggers extra queries even with optimizer enabled.

Solution: Add only hints to custom fields and model properties:

from decimal import Decimal
@strawberry_django.field(only=["price", "quantity"])
def total(self) -> Decimal:
return self.price * self.quantity

Mutations and Relationships

Problem: After creating related objects in a mutation, they don’t appear in the response.

Cause: Django caches the related manager before the objects are created.

Solution: Refresh the object or fetch it again:

from django.db import transaction
@strawberry_django.mutation
@transaction.atomic
def create_author_with_books(self, data: AuthorInput) -> Author:
author = models.Author.objects.create(name=data.name)
for book_data in data.books:
models.Book.objects.create(
author=author,
title=book_data.title,
# Add other fields explicitly
)
# βœ… Option 1: Refresh from database
author.refresh_from_db()
# βœ… Option 2: Fetch again (better for optimizer)
# return models.Author.objects.get(pk=author.pk)
return author

ListInput Not Updating Many-to-Many Relations

Problem: Using ListInput with set , add , or remove doesn’t update relationships.

Solution: Ensure you’re using the correct field type and handling the operations:

@strawberry_django.partial(models.Article)
class ArticleInputPartial(NodeInput):
title: auto
tags: ListInput[strawberry.ID] | None = None # βœ… ListInput for M2M
@strawberry_django.mutation
def update_article(self, data: ArticleInputPartial) -> Article:
article = models.Article.objects.get(pk=data.id)
if data.tags is not strawberry.UNSET and data.tags is not None:
if data.tags.set is not None:
article.tags.set(data.tags.set)
if data.tags.add is not None:
article.tags.add(*data.tags.add)
if data.tags.remove is not None:
article.tags.remove(*data.tags.remove)
article.save()
return article

See Nested Mutations guide for comprehensive examples.

Polymorphic Models in ListInput

Problem: Updating M2M with polymorphic models removes objects incorrectly.

Cause: Concrete model instances aren’t matched with abstract base model instances in the existing set.

Workaround: Use InheritanceManager with proper subclass selection:

from model_utils.managers import InheritanceManager
class Project(models.Model):
# ...
objects = InheritanceManager()

Then ensure relationships use select_subclasses() :

existing = set(manager.select_subclasses() if isinstance(manager, InheritanceManager) else manager.all())

See GitHub Issue #793 for details.

Validation Errors Not Showing Field Information

Problem: Validation errors don’t indicate which field had an error.

Solution: Use Django’s dict-style ValidationError:

from django.core.exceptions import ValidationError
# ❌ No field info
raise ValidationError("Invalid email")
# βœ… With field info
raise ValidationError({'email': 'Invalid email address'})
# βœ… Multiple fields
raise ValidationError({
'email': 'Invalid email address',
'age': 'Must be at least 18'
})

Permissions and Authentication

Permission Extensions Not Working

Problem: Permission checks are not enforced.

Cause: Extensions may not be properly configured or the user context isn’t set.

Solution: Ensure proper setup:

# 1. Check extension is added to the field
@strawberry_django.field(extensions=[IsAuthenticated()])
def sensitive_data(self) -> str:
return self.data
# 2. Ensure Django middleware is configured
MIDDLEWARE = [
# ...
'django.contrib.auth.middleware.AuthenticationMiddleware',
# ...
]
# 3. For async views, use AuthGraphQLProtocolTypeRouter
from strawberry_django.routers import AuthGraphQLProtocolTypeRouter

Getting Current User Returns None

Problem: get_current_user(info) returns None even when authenticated.

Solution: Check request setup:

from strawberry_django.auth.utils import get_current_user
def resolver(self, info: Info):
request = info.context.request
print(f"Authenticated: {request.user.is_authenticated}") # Debug
user = get_current_user(info)
return user

Ensure authentication middleware is properly configured and the view is set up correctly.

Filters and Ordering

DISTINCT Filter Causing Wrong totalCount

Problem: Using DISTINCT=true in filters returns incorrect totalCount in connections.

Cause: COUNT queries with DISTINCT on joined tables can produce incorrect results.

Workaround: Use a subquery or custom totalCount resolver:

import strawberry
@strawberry.field
def total_count(self, root) -> int:
# Custom count logic that handles DISTINCT properly
return root.values('pk').distinct().count()

Filter on Relationships Not Working

Problem: Filtering by related model fields doesn’t work.

Solution: Ensure the filter relationship chain is correct:

@strawberry_django.filter_type(models.Color)
class ColorFilter:
id: auto
name: auto
@strawberry_django.filter_type(models.Fruit)
class FruitFilter:
id: auto
name: auto
color: ColorFilter | None # βœ… Proper relationship filter

Query with correct nesting:

query {
fruits(filters: { color: { name: "red" } }) {
id
name
}
}

Ordering Not Respecting Variable Order

Problem: Multiple ordering fields don’t respect the order specified in variables.

Cause: Dict ordering may not be preserved in some Python versions or implementations.

Solution: Use a list of ordering inputs with the new @strawberry_django.order_type :

@strawberry_django.order_type(models.Fruit)
class FruitOrder:
name: auto
created: auto

Query:

query {
fruits(ordering: [{ name: ASC }, { created: DESC }]) {
id
name
}
}

Relay and Global IDs

Global ID Mapping Not Working

Problem: auto fields for IDs aren’t mapped to GlobalID even with MAP_AUTO_ID_AS_GLOBAL_ID=True .

Solution: Ensure the setting is properly configured and types inherit from relay.Node :

settings.py
STRAWBERRY_DJANGO = {
"MAP_AUTO_ID_AS_GLOBAL_ID": True,
}
types.py
from strawberry.relay import Node
@strawberry_django.type(models.Fruit)
class Fruit(Node): # βœ… Inherit from Node
id: auto # Will be mapped to GlobalID
name: auto

Custom Node Resolver Not Working

Problem: Custom resolve_node logic isn’t being called.

Solution: Ensure you’re overriding the correct method:

import strawberry
from strawberry.relay import Node
@strawberry_django.type(models.Fruit)
class Fruit(Node):
@classmethod
def resolve_id(cls, root, info) -> strawberry.ID:
# Custom ID resolution
return strawberry.ID(f"custom_{root.pk}")
@classmethod
def resolve_nodes(cls, info, node_ids, required=False):
# Custom node fetching
return models.Fruit.objects.filter(pk__in=node_ids)

Subscriptions

Subscriptions Not Working

Problem: Websocket connections fail or subscriptions don’t receive updates.

Solution: Ensure proper ASGI and channels setup:

asgi.py
import os
from django.core.asgi import get_asgi_application
from strawberry_django.routers import AuthGraphQLProtocolTypeRouter
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
django_asgi_app = get_asgi_application()
from .schema import schema
application = AuthGraphQLProtocolTypeRouter(
schema,
django_application=django_asgi_app,
)
settings.py
INSTALLED_APPS = [
'daphne', # Must be before 'django.contrib.staticfiles'
'django.contrib.staticfiles',
# ...
]
ASGI_APPLICATION = 'project.asgi.application'

Testing

Async Test Errors

Problem: RuntimeError: no running event loop in async tests.

Solution: Use pytest-asyncio and mark tests properly:

import pytest
@pytest.mark.django_db
@pytest.mark.asyncio
async def test_async_resolver():
result = await some_async_function()
assert result is not None

Test Client Authentication Not Working

Problem: Authentication doesn’t persist in test client.

Solution: Use the login context manager:

from strawberry_django.test.client import TestClient
def test_authenticated_query(db):
user = User.objects.create_user(username='test')
client = TestClient("/graphql")
with client.login(user): # βœ… Use context manager
res = client.query("""
query {
me {
username
}
}
""")
assert res.data["me"]["username"] == "test"

Performance Issues

Slow Queries with Large Datasets

Problem: Queries are slow with large result sets.

Solutions:

  1. Enable pagination:
@strawberry_django.type(models.Fruit, pagination=True)
class Fruit:
name: auto
  1. Use cursor-based pagination for very large datasets:
from strawberry_django.relay import DjangoCursorConnection
@strawberry.type
class Query:
fruits: DjangoCursorConnection[Fruit] = strawberry_django.connection()
  1. Add database indexes to filtered/ordered fields:
class Fruit(models.Model):
name = models.CharField(max_length=100, db_index=True)
created = models.DateTimeField(db_index=True)

Memory Issues with Large Responses

Problem: Server runs out of memory with large queries.

Solution: Implement pagination limits and use streaming:

settings.py
STRAWBERRY_DJANGO = {
"PAGINATION_DEFAULT_LIMIT": 100, # Limit results
}

IDE and Type Checking

PyLance/Mypy Type Errors

Problem: Type checker shows errors on strawberry.auto or casts.

Solution: Use proper type annotations and casts:

from typing import cast
@strawberry_django.mutation
def create_fruit(self, name: str) -> Fruit:
fruit = models.Fruit.objects.create(name=name)
return cast(Fruit, fruit) # βœ… Help type checker

Getting Help

If your issue isn’t covered here:

  1. Check existing issues: Search GitHub Issues
  2. Check discussions: Look at GitHub Discussions
  3. Join Discord: Ask in the Strawberry Discord
  4. Review examples: Check the example app
  5. Enable debug logging: Add logging to see what’s happening:
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger('strawberry_django')
logger.setLevel(logging.DEBUG)

See Also