Skip to content

team_index route returns 500 due to lazy-loaded relationship in sync template rendering #66

Description

@oransom

The GET /{team_slug} route (team_index in routers/team.py) crashes with sqlalchemy.exc.MissingGreenlet when rendering the team dashboard.

Root cause

The deployments query eager-loads Deployment.aliases but not Deployment.project:

select(Deployment)
.options(selectinload(Deployment.aliases))
.join(Project)
...

The template (deployment/macros/list.html) then accesses deployment.project.name, deployment.project.slug, and deployment.environment (a @Property that internally reads self.project). These accesses trigger a lazy load of the project relationship during Jinja2's
synchronous template.render() call, which cannot execute an async DB query — hence MissingGreenlet.

This likely went unnoticed because the ORM identity map usually had Project objects cached from earlier queries in the same request. A Docker restart (or any scenario that clears session state) makes the lazy load actually hit the database, surfacing the bug.

Fix

Add selectinload(Deployment.project) to the deployments query in team_index:

select(Deployment)
.options(selectinload(Deployment.aliases), selectinload(Deployment.project))
.join(Project)
...

Note: .join(Project) only uses Project for filtering — it does not populate the relationship on the result objects. selectinload is needed for that.

Affected file: app/routers/team.py, line ~115

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions