Replies: 3 comments
-
|
This is expected behavior when using SQLModel together with Streamlit’s hot-reload Even if you manage your own registry inside sys.modules, SQLModel’s internal base continues to 🔍 Why the SAWarning appearsOn every Streamlit reload:
Clearing your own registry does not help because:
This leads to the repeated warnings, and in some cases, escalates to: because SQLModel’s global metadata still contains the table from the first load. ❗ Root Cause (important)SQLModel defines its own declarative system: class SQLModel(declarative_base()):
metadata = SQLModelMetadata |
Beta Was this translation helpful? Give feedback.
-
|
The issue happens because SQLModel uses a global declarative base and metadata, and Streamlit
Any of these solutions will stop SQLModel from re-registering models on reload and remove the |
Beta Was this translation helpful? Give feedback.
-
|
You can try using @st.cache_resource to cache imports. Other imports can be defined as usual. Note, that if you changed something in modules imported this way, changes will not take effect until you restart application. @st.cache_resource
def get_imports():
"""Cache imports to avoid SQLAlchemy table redefinition errors."""
from src.database import get_session_context
from src.product.models import ProductStatus
return (
get_session_context,
ProductStatus,
)
(
get_session_context,
ProductStatus,
) = get_imports() |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
First Check
Commit to Help
Example Code
Description
Environment
Framework: Streamlit (with st.cache_resource)
ORM: SQLModel (built on SQLAlchemy 2.x)
Language: Python 3.13
Context: Running a modularized app using SQLModel models and a custom registry, inside a Streamlit app that uses st.cache_resource to persist an SQLProvider instance.
Problem
Every time Streamlit performs a hot reload (e.g. when code changes or the script re-runs), the SQLModel models are re-imported, causing SQLAlchemy to re-register existing ORM classes on the same DeclarativeBase.
This leads to warnings such as:
SAWarning: This declarative base already contains a class with the same class name and module name as src.core.models.FoodItem, and will be replaced in the string-lookup table.
Even though we manage a shared registry across reloads via sys.modules and clear the metadata/registry on reload, SQLModel still re-adds models to its internal base and triggers these warnings.
Expected Behavior
SQLModel or SQLAlchemy should detect identical re-registrations and skip duplicates on reloads.
Streamlit hot reload should not cause multiple declarative model registrations for the same Base.
Actual Behavior
Each Streamlit reload causes SQLModel’s global declarative base to retain the previous model class definitions.
SQLModel re-registers new class objects with identical names → triggering repeated SAWarning.
This warning repeats for each ORM class on every reload.
In some configurations (without manual registry cleanup), it escalates to a sqlalchemy.exc.InvalidRequestError (“table already defined”).
Operating System
macOS
Operating System Details
M1 Mac
OS: 26.0.1 (25A362)
SQLModel Version
0.0.27
Python Version
Python 3.13.7
Additional Context
No response
Beta Was this translation helpful? Give feedback.
All reactions