Skip to content

[Bug]: table=True with custom registry= stores bool in model_config and leaves model unmapped #2046

Description

@baiyuxi930826

Describe the bug

Passing table=True together with a custom registry= stores the boolean table flag into model_config["registry"] instead of the registry object, and the model is left unmapped.

In sqlmodel/main.py (SQLModelMetaclass):

config_registry = get_config("registry")
if config_registry is not Undefined:
    config_registry = cast(registry, config_registry)
    # If it was passed by kwargs, ensure it's also set in config
    new_cls.model_config["registry"] = config_table   # BUG: should be config_registry
    setattr(new_cls, "_sa_registry", config_registry)
    setattr(new_cls, "metadata", config_registry.metadata)
    setattr(new_cls, "__abstract__", True)

Debug information

  • Repo checkout @ 803a3d1f6d605a1da45ed166120845ed54ce9c2a
  • Python 3.12

Repro steps

from sqlalchemy.orm import registry
from sqlmodel import SQLModel, Field

reg = registry()

class Hero(SQLModel, table=True, registry=reg):
    id: int | None = Field(default=None, primary_key=True)
    name: str

print(Hero.model_config["registry"])  # True  (expected: the registry object)
print(hasattr(Hero, "__mapper__"))    # False

# Session usage typically raises sqlalchemy.orm.exc.UnmappedClassError
# Subclassing also breaks: AttributeError: 'bool' object has no attribute 'metadata'

Default path works: class Hero(SQLModel, table=True).

Expected behavior

model_config["registry"] should hold the provided registry; the table model should be mapped like the default-registry table=True path.

Actual behavior

model_config["registry"] is True; model has no mapper; multi-registry one-shot API is unusable.

Suggested direction

new_cls.model_config["registry"] = config_registry

Also reconsider always setting __abstract__ = True when a custom registry is provided on a table=True model.

I'd be happy to prepare a PR with a regression test if this is confirmed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions