Skip to content

NoReferencedTableError: ForeignKey resolution fails when db.schema is configured #116

@ZechCodes

Description

@ZechCodes

Summary

When db.schema is configured in app.yaml (e.g., schema: runhacks), ForeignKey("users.id") references in application models fail with NoReferencedTableError during INSERT operations.

Root Cause

In create_app() (asgi.py), controllers are loaded (line ~655) before Base.metadata.schema is set (line ~667):

controllers = load_controllers()   # imports all models → tables registered as "users", "emails", etc.
# ...
Base.metadata.schema = settings.db.db_schema   # now metadata schema = "runhacks"

After this, Skrift tables (like users) are registered in Base.metadata.tables under bare keys (e.g., "users"), but when SQLAlchemy resolves ForeignKey("users.id"), it uses the metadata's schema to qualify the lookup, searching for "runhacks.users" — which doesn't exist.

Reproduction

Any model that references Skrift's users table via ForeignKey("users.id") will fail on INSERT/flush:

class MyModel(Base):
    __tablename__ = "my_table"
    user_id: Mapped[UUID] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"), nullable=False
    )
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 
'my_table.user_id' could not find table 'runhacks.users' with which to 
generate a foreign key to target column 'id'

Suggested Fix

Either:

  1. Set Base.metadata.schema before loading controllers/models
  2. After setting the schema, re-register existing tables under schema-qualified keys:
    for key in list(Base.metadata.tables.keys()):
        if "." not in key:
            qualified = f"{schema}.{key}"
            if qualified not in Base.metadata.tables:
                Base.metadata.tables._insert_item(qualified, Base.metadata.tables[key])

Current Workaround

We apply option 2 in our asgi.py after importing skrift.asgi.app.

Environment

  • Skrift 0.1.0a71 (also confirmed on a85)
  • SQLAlchemy 2.x
  • PostgreSQL with schema isolation (db.schema: runhacks)

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