{"id":"8e836a280d9a842f","repo":"sqlalchemy/sqlalchemy","slug":"no-type-information-could-be-extracted-from-annota","errorCode":null,"errorMessage":"No type information could be extracted from annotation {annotation} for attribute '{base.__name__}.{name}'","messagePattern":"No type information could be extracted from annotation (.+?) for attribute '(.+?)\\.(.+?)'","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/sqlalchemy/sql/_annotated_cols.py","lineNumber":279,"sourceCode":"        cls_annotations = util.get_annotations(base)\n        cls_vars = vars(base)\n        items = [\n            (n, cls_vars.get(n), cls_annotations.get(n))\n            for n in util.merge_lists_w_ordering(\n                list(cls_vars), list(cls_annotations)\n            )\n            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","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/sqlalchemy/sqlalchemy/blob/d9b44cb731bd27e6e82c99a3c0fb598214e8e7ff/lib/sqlalchemy/sql/_annotated_cols.py#L261-L297","documentation":"When a TypedColumns attribute has only an annotation (no Column instance) SQLAlchemy extracts a Python type from the annotation to infer the SQL type. If _collect_annotation cannot extract any usable type (returns _NoArg.NO_ARG) - e.g. the annotation is bare Named/Column with no parameter, or resolves to a non-generic base - an ArgumentError is raised naming the offending annotation and attribute.","triggerScenarios":"Declaring an attribute like `name: Named` (missing type arg) or `name: SomeNonGenericType` in a TypedColumns subclass. Also triggered by annotations that de-stringify to a bare Named/Column class rather than a generic like Named[str].","commonSituations":"Forgetting the type parameter on Named, using forward references that resolve to the wrong shape, or copy-pasting annotation styles that work in ORM mapped classes but are too vague for TypedColumns inference.","solutions":["Provide a concrete type argument to Named or Column: `name: Named[str]` or `name: Column[String]`","Ensure forward references (string annotations) resolve to a generic Named[...] / Column[...] at evaluation time","If you need full control over the type, assign a Column instance instead of relying on annotation inference: `name = Column(String)`"],"exampleFix":"# before\nclass Cols(TypedColumns):\n    name: Named   # no type info extractable\n\n# after\nclass Cols(TypedColumns):\n    name: Named[str]","handlingStrategy":"validation","validationCode":"import typing\n# Surface annotation problems BEFORE building the table\nhints = typing.get_type_hints(MyCols)\nfor name, ann in hints.items():\n    origin = typing.get_origin(ann)\n    args = typing.get_args(ann)\n    if origin is None or not args:\n        raise ValueError(\n            f\"{MyCols.__name__}.{name}: annotation {ann!r} carries no inner type; \"\n            \"use Column[<pytype>] or Named[<pytype>].\"\n        )","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use parameterized annotations like `Column[int]` / `Named[str]` so SQLAlchemy can extract a concrete type.","Avoid bare `Column` or `Named` without a type parameter on TypedColumns attributes.","Ensure any name referenced in a string annotation is importable in the class's module."],"tags":["sqlalchemy","typed-columns","typing","annotation","argument-error"],"analyzedSha":"d9b44cb731bd27e6e82c99a3c0fb598214e8e7ff","analyzedAt":"2026-08-01T17:20:52.075Z","schemaVersion":2}