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:
- Set
Base.metadata.schema before loading controllers/models
- 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)
Summary
When
db.schemais configured inapp.yaml(e.g.,schema: runhacks),ForeignKey("users.id")references in application models fail withNoReferencedTableErrorduring INSERT operations.Root Cause
In
create_app()(asgi.py), controllers are loaded (line ~655) beforeBase.metadata.schemais set (line ~667):After this, Skrift tables (like
users) are registered inBase.metadata.tablesunder bare keys (e.g.,"users"), but when SQLAlchemy resolvesForeignKey("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
userstable viaForeignKey("users.id")will fail on INSERT/flush:Suggested Fix
Either:
Base.metadata.schemabefore loading controllers/modelsCurrent Workaround
We apply option 2 in our
asgi.pyafter importingskrift.asgi.app.Environment
db.schema: runhacks)