You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Field(allow_mutation=False) doesn't have same behavior as pydantic #262
When setting a Field(allow_mutation=False) in combination with the required validate_assignment = True configuration on a SQLModel, the framework doesn't even allow the field to be set in the initial construction of the model. This is allowed in pydantic. I've attached a test suite that we should expect to pass, but it fails both the SQLModel specific tests.
Several issues have been reported about inconsistencies between sqlmodel and pydantic: #87, #230, etc. This particular issue is caused by these lines in main.py:
# Do not set values as in Pydantic, pass them through setattr, so SQLAlchemy
# can handle them
# object.__setattr__(__pydantic_self__, '__dict__', values)
object.__setattr__(__pydantic_self__, "__fields_set__", fields_set)
for key, value in values.items():
setattr(__pydantic_self__, key, value)
The last line is assignment, which is forbidden by allow_mutation=False. Unfortunately, the problem is not so easily fixed, because the handling of attributes is rather complex in sqlmodel. I have fixed it here, but it feels like duct tape.
Reacted by Toni Alatalo, David Volm, Jiamin Zhu, William Ellwood and gvoysey
I am having the same problem at version 0.0.24, and even setting validate_assignment = False doesn't work anymore. Actually, my problem has to do with frozen=True argument instead of the allow_mutation=False argument, as the later is deprecated at the pydantic side and doesn't even do anything anymore (which also means that the SQLModel API interface should be updated as well).
Below is an example stacktrace, where UserDB is a SQLModel with a table=True, and has a field like this:
date_of_creation: datetime=Field(
# allow_mutation=True, # This seems meaningless as it is a pydantic v1 argumentdefault_factory=datetime.now,
schema_extra={"frozen": True} # see https://github.com/fastapi/sqlmodel/issues/262#issuecomment-1060041950
)
The stacktrace is as follows:
File "D:\Projects\server\backend\source\data\models\user.py", line 75, in sql
return UserDB(**self.dict())
^^^^^^^^^^^^^^^^^^^^^
File "<string>", line 4, in __init__
File "D:\Projects\server\backend\.venv\Lib\site-packages\sqlalchemy\orm\state.py", line 571, in _initialize_instance
with util.safe_reraise():
File "D:\Projects\server\backend\.venv\Lib\site-packages\sqlalchemy\util\langhelpers.py", line 146, in __exit__
raise exc_value.with_traceback(exc_tb)
File "D:\Projects\server\backend\.venv\Lib\site-packages\sqlalchemy\orm\state.py", line 569, in _initialize_instance
manager.original_init(*mixed[1:], **kwargs)
File "D:\Projects\server\backend\.venv\Lib\site-packages\sqlmodel\main.py", line 814, in __init__
sqlmodel_init(self=__pydantic_self__, data=data)
File "D:\Projects\server\backend\.venv\Lib\site-packages\sqlmodel\_compat.py", line 356, in sqlmodel_init
sqlmodel_table_construct(
File "D:\Projects\server\backend\.venv\Lib\site-packages\sqlmodel\_compat.py", line 275, in sqlmodel_table_construct
setattr(self_instance, key, value)
File "D:\Projects\server\backend\.venv\Lib\site-packages\sqlmodel\main.py", line 827, in __setattr__
super().__setattr__(name, value)
File "D:\Projects\server\backend\.venv\Lib\site-packages\pydantic\main.py", line 875, in __setattr__
self._check_frozen(name, value)
File "D:\Projects\server\backend\.venv\Lib\site-packages\pydantic\main.py", line 939, in _check_frozen
raise pydantic_core.ValidationError.from_exception_data(self.__class__.__name__, [error])
pydantic_core._pydantic_core.ValidationError: 1 validation error for UserDB
date_of_creation
Field is frozen [type=frozen_field, input_value=datetime.datetime(2025, 4, 13, 18, 42, 57, 637768), input_type=datetime]
For further information visit https://errors.pydantic.dev/2.9/v/frozen_field
The last callstack at the SQLModel side is here. I wanted to fix it, but it seems so deep down in the callstack, and is nested inside multiple dunder method calls, so I have no idea how to even start fixing that.
Also, can we get a bug label for this issue please?
Use case of @EkremDincel is a bit different. And it still doesn't work.
It shows the inability to instantiate model with table=True and immutable field:
importsqlmodelclassMySqlmodelModel(sqlmodel.SQLModel, table=True):
id: str=sqlmodel.Field(primary_key=True)
data: str=sqlmodel.Field(schema_extra={"frozen": True})
model_config= {"validate_assignment": True}
classTestSuite:
deftest_sqlmodel_can_create(self):
MySqlmodelModel(id="abc", data="foo")
# 1 validation error for MySqlmodelModel# data# Field is frozen
Activity
byrman commentedon Mar 6, 2022
Several issues have been reported about inconsistencies between sqlmodel and pydantic: #87, #230, etc. This particular issue is caused by these lines in main.py:
The last line is assignment, which is forbidden by
allow_mutation=False. Unfortunately, the problem is not so easily fixed, because the handling of attributes is rather complex in sqlmodel. I have fixed it here, but it feels like duct tape.WalkerWalker commentedon Jan 14, 2023
I also hope the immutatable model can be possible in sqlmodel. The same problem is reported in stackoverflow here
The problem still exists in 0.0.8
tepelbaum commentedon Jan 14, 2024
Hi! Does the recent version of SQLModel (0.0.14) solves the issue? :)
EkremDincel commentedon Apr 13, 2025
I am having the same problem at version 0.0.24, and even setting
validate_assignment = Falsedoesn't work anymore. Actually, my problem has to do withfrozen=Trueargument instead of theallow_mutation=Falseargument, as the later is deprecated at the pydantic side and doesn't even do anything anymore (which also means that the SQLModel API interface should be updated as well).Below is an example stacktrace, where
UserDBis a SQLModel with atable=True, and has a field like this:The stacktrace is as follows:
The last callstack at the SQLModel side is here. I wanted to fix it, but it seems so deep down in the callstack, and is nested inside multiple dunder method calls, so I have no idea how to even start fixing that.
Also, can we get a
buglabel for this issue please?YuriiMotov commentedon Aug 27, 2025
I just tested it with SQLAlchemy 0.0.24, Pydantic 1.10.22 / 2.11.7 and tests pass.
Here is adapted test (in order to work with both, Pydantic V1 and V2) (in the details):
Details
Use case of @EkremDincel is a bit different. And it still doesn't work.
It shows the inability to instantiate model with
table=Trueand immutable field: