All writing
python debugging sqlalchemy fastapi

Fixing SQLAlchemy MissingGreenlet Error in FastAPI (Async Explained)

Ayush Kaushik 3 min read
Fixing SQLAlchemy MissingGreenlet Error in FastAPI (Async Explained)

Introduction

If you’re using FastAPI with SQLAlchemy 2.0 async and suddenly hit a MissingGreenlet error, you’re not alone.

This error usually appears when async database calls are executed outside the proper event loop context -often due to incorrect session management, blocking calls, or mixing sync and async patterns.

The problem is not FastAPI.

And it’s usually not SQLAlchemy either.

It’s almost always an architectural issue in how async SQLAlchemy is wired into your FastAPI application.

In this article, we’ll break down what MissingGreenlet actually means, why it happens in real-world FastAPI projects, and how to fix it correctly - without hacks or workarounds.

The Problem

You just migrated your FastAPI application to Async SQLAlchemy 2.0. You run your code, everything looks fine, and then bam. Your API crashes with this scary error message:

Plaintext

sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called; can't call await_only() function.

If you are seeing this, you are not alone. This is the #1 pitfall developers encounter when switching from synchronous to asynchronous database calls.


The Cause

This error happens when you try to access a Relationship attribute (like user.posts) that was not loaded in the original query.

In the old synchronous world, SQLAlchemy would “lazily” load this data for you. It would silently pause your code, run a quick SQL query to get the posts, and then continue.

In the Async world, this is illegal. SQLAlchemy cannot pause the event loop to run a synchronous “lazy load” query. Since it can’t run the query, it crashes.

Poor lifecycle management is one of the most common causes of database connection leaks in FastAPI, which can silently kill production systems.

The Solution (Eager Loading)

To fix this, you must tell SQLAlchemy to fetch the related data upfront using “Eager Loading” strategies like selectinload or joinedload.

The Broken Code (Lazy Loading):

Python

# This query only fetches the User, not their posts
query = select(User).where(User.id == 1)
result = await session.execute(query)
user = result.scalar_one()
# CRASH HAPPENS HERE 💥
# SQLAlchemy tries to fetch 'posts' synchronously, but can't.
print(user.posts)

The Fix (Eager Loading): Import selectinload and add it to your query options.

Python

from sqlalchemy.orm import selectinload
# Tell SQLAlchemy to fetch 'posts' immediately
query = select(User).options(selectinload(User.posts)).where(User.id == 1)
result = await session.execute(query)
user = result.scalar_one()
# Works perfectly! The data is already there.
print(user.posts)

Which Option Should You Use?

  • selectinload: Best for One-to-Many relationships (e.g., User -> Posts). It runs two separate queries (one for users, one for posts) which is often faster for lists.

  • joinedload: Best for Many-to-One relationships (e.g., Post -> Author). It runs a single query with a SQL JOIN.

This error is one of several common failure modes in improperly structured FastAPI + SQLAlchemy 2.0 async architectures.

This repository demonstrates how correct lifecycle management prevents errors like MissingGreenlet: https://github.com/AyushKaushik-BD/fastapi-sqlalchemy-async-patterns

My Personal Tip

If you want to prevent this error from ever happening again, you can disable lazy loading entirely in your model configuration. This forces you to be explicit about your queries, which is better for performance anyway.

Python

# In your model definition
class User(Base):
__tablename__ = "users"
# Raise an error if you forget to load data
posts = relationship("Post", lazy="raise_on_sql")

Next Steps

Now that you have fixed your relationships, make sure your entire AsyncEngine is configured correctly. Check out my Complete Guide to Async FastAPI & SQLAlchemy 2.0 for a full production setup.

Working on something similar?

If you're building backend or AI systems and want a second set of senior eyes, let's talk.

Keep reading

Related articles