{"id":"78b363f53b80772f","repo":"sqlalchemy/sqlalchemy","slug":"could-not-find-a-sql-type-for-type-extracted-type","errorCode":null,"errorMessage":"Could not find a SQL type for type {extracted_type} obtained from annotation {annotation} in attribute '{base.__name__}.{name}'","messagePattern":"Could not find a SQL type for type (.+?) obtained from annotation (.+?) in attribute '(.+?)\\.(.+?)'","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/sqlalchemy/sql/_annotated_cols.py","lineNumber":286,"sourceCode":"            if not dunders_re.match(n)\n        ]\n        # --\n        for name, obj, annotation in items:\n            if obj is None:\n                assert annotation is not None\n                # no attribute, just annotation\n                extracted_type = _collect_annotation(\n                    table_columns_cls, name, base.__module__, annotation\n                )\n                if extracted_type is _NoArg.NO_ARG:\n                    raise ArgumentError(\n                        \"No type information could be extracted from \"\n                        f\"annotation {annotation} for attribute \"\n                        f\"'{base.__name__}.{name}'\"\n                    )\n                sqltype = _get_sqltype(extracted_type)\n                if sqltype is None:\n                    raise ArgumentError(\n                        f\"Could not find a SQL type for type {extracted_type} \"\n                        f\"obtained from annotation {annotation} in \"\n                        f\"attribute '{base.__name__}.{name}'\"\n                    )\n                columns[name] = Column(\n                    name,\n                    sqltype,\n                    nullable=sa_typing.includes_none(extracted_type),\n                )\n            elif isinstance(obj, Column):\n                # has attribute attribute\n                # _DeclarativeMapperConfig._produce_column_copies\n                # as with orm this case is not supported\n                for fk in obj.foreign_keys:\n                    if (\n                        fk._table_column is not None\n                        and fk._table_column.table is None\n                    ):","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/sqlalchemy/sqlalchemy/blob/d9b44cb731bd27e6e82c99a3c0fb598214e8e7ff/lib/sqlalchemy/sql/_annotated_cols.py#L268-L304","documentation":"After extracting a Python type from a Named[...] / Column[...] annotation, SQLAlchemy looks it up in its built-in python-to-SQL type map (sqltypes._type_map). If the Python type has no registered SQL equivalent (e.g. dict, complex, a custom class), _get_sqltype returns None and ArgumentError is raised showing both the extracted Python type and the original annotation.","triggerScenarios":"Annotating a column with an unsupported Python type: `data: Named[dict]`, `val: Named[complex]`, or `obj: Named[MyCustomClass]` where MyCustomClass has no TypeEngine mapping. The supported set covers bool, int, float, str, bytes, datetime, Decimal, UUID, etc.","commonSituations":"Assuming any Python type can be mapped (e.g. wanting JSON and writing Named[dict] instead of using the JSON SQL type), or using domain/dataclass types as column annotations without registering a SQL type decorator.","solutions":["Use a SQL type directly via a Column instance: `data = Column(JSON)` or `data: Named[str] = Column(JSON)`","Pick a supported builtin Python type (str, int, float, bytes, bool, Decimal, datetime, UUID) for inference","Register a custom TypeEngine decorator and reference it explicitly through a Column instance rather than relying on the python-type map"],"exampleFix":"# before\nclass Cols(TypedColumns):\n    payload: Named[dict]  # no SQL type for dict\n\n# after\nfrom sqlalchemy import JSON\nclass Cols(TypedColumns):\n    payload = Column(JSON)","handlingStrategy":"validation","validationCode":"import datetime, decimal, uuid\nfrom sqlalchemy import types as sqltypes\n\nTYPE_MAP = {\n    int: sqltypes.Integer, str: sqltypes.String, float: sqltypes.Float,\n    bool: sqltypes.Boolean, bytes: sqltypes.LargeBinary,\n    datetime.datetime: sqltypes.DateTime, datetime.date: sqltypes.Date,\n    datetime.time: sqltypes.Time, decimal.Decimal: sqltypes.Numeric,\n    uuid.UUID: sqltypes.Uuid,\n}\ndef ensure_mappable(py_type) -> None:\n    if py_type not in TYPE_MAP:\n        raise ValueError(\n            f\"No built-in SQL type for {py_type!r}; \"\n            \"register a TypeDecorator or set the type on the Column explicitly.\"\n        )","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Stick to Python primitives SQLAlchemy maps automatically (int, str, float, bool, bytes, datetime, Decimal, UUID).","For custom/enum types, subclass `sqlalchemy.types.TypeDecorator` and annotate with that subclass.","If a type is exotic, pass it directly to Column (`Column(type_=MyType())`) instead of relying on the annotation alone."],"tags":["sqlalchemy","typed-columns","typing","type-mapping","argument-error"],"analyzedSha":"d9b44cb731bd27e6e82c99a3c0fb598214e8e7ff","analyzedAt":"2026-08-01T17:20:52.075Z","schemaVersion":2}