{"id":"3cfbc8128e19a1a8","repo":"sqlalchemy/sqlalchemy","slug":"unexpected-value-for-attribute-base-name-n","errorCode":null,"errorMessage":"Unexpected value for attribute '{base.__name__}.{name}'. Expected a Column, not: {type(obj)}","messagePattern":"Unexpected value for attribute '(.+?)\\.(.+?)'\\. Expected a Column, not: (.+?)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/sqlalchemy/sql/_annotated_cols.py","lineNumber":350,"sourceCode":"                    if anno_sqltype is None and not col.foreign_keys:\n                        raise ArgumentError(\n                            \"Python typing annotation is required for \"\n                            f\"attribute '{base.__name__}.{name}' when \"\n                            \"primary argument(s) for Column construct are \"\n                            \"None or not present\"\n                        )\n                    elif anno_sqltype is not None:\n                        col._set_type(anno_sqltype)\n\n                if (\n                    nullable is not _NoArg.NO_ARG\n                    and col._user_defined_nullable is NULL_UNSPECIFIED\n                    and not col.primary_key\n                ):\n                    col.nullable = nullable\n                columns[name] = col\n            else:\n                raise ArgumentError(\n                    f\"Unexpected value for attribute '{base.__name__}.{name}'\"\n                    f\". Expected a Column, not: {type(obj)}\"\n                )\n\n    # Return columns as a list\n    return list(columns.values())\n\n\n@util.preload_module(\"sqlalchemy.sql.schema\")\ndef _collect_annotation(\n    cls: type[Any], name: str, module: str, raw_annotation: _AnnotationScanType\n) -> _AnnotationScanType | Literal[_NoArg.NO_ARG]:\n    Column = util.preloaded.sql_schema.Column\n\n    _locals = {\"Column\": Column, \"Named\": Named}\n    # _ClassScanAbstractConfig._collect_annotation & _extract_mapped_subtype\n    try:\n        annotation = sa_typing.de_stringify_annotation(","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/sqlalchemy/sqlalchemy/blob/d9b44cb731bd27e6e82c99a3c0fb598214e8e7ff/lib/sqlalchemy/sql/_annotated_cols.py#L332-L368","documentation":"_extract_columns_from_class iterates each non-dunder attribute of a TypedColumns subclass. An attribute is expected to be either None (annotation-only) or a Column instance. Any other value type (an int, a string, a ColumnClause, a relationship, a random object) is rejected with ArgumentError showing the actual type, because the column-extraction logic has no way to interpret it.","triggerScenarios":"Assigning a non-Column value as a class attribute in a TypedColumns subclass: `count = 5`, `label = 'default'`, `related = relationship(...)`, or `c = column('x')` (a ColumnClause, not schema.Column).","commonSituations":"Treating TypedColumns like an ORM mapped class and adding class-level constants, defaults, or relationship() calls. Also occurs when importing the wrong Column (e.g. sqlalchemy.sql.expression.column instead of sqlalchemy.Column).","solutions":["Remove the non-column attribute or move it elsewhere (constant, mixin, separate class)","If it should be a column, use schema.Column: `from sqlalchemy import Column` and assign a Column instance","If it is metadata for type checkers only, prefix with an underscore or place it outside the TypedColumns subclass"],"exampleFix":"# before\nfrom sqlalchemy.sql import column  # wrong column\nclass Cols(TypedColumns):\n    c = column('x')  # ColumnClause, not schema.Column -> rejected\n\n# after\nfrom sqlalchemy import Column, String\nclass Cols(TypedColumns):\n    c = Column('x', String)","handlingStrategy":"type-guard","validationCode":"from sqlalchemy import Column\n\ndef validate_attribute(name, obj) -> None:\n    if obj is not None and not isinstance(obj, Column):\n        raise TypeError(\n            f\"TypedColumns attribute {name!r} must be a Column, \"\n            f\"got {type(obj).__name__}\"\n        )","typeGuard":"from sqlalchemy import Column\n\ndef is_valid_column_attr(obj) -> bool:\n    \"\"\"True only for None or a Column (valid TypedColumns attribute values).\"\"\"\n    return obj is None or isinstance(obj, Column)","tryCatchPattern":null,"preventionTips":["In TypedColumns subclasses, assign only `Column(...)` objects or nothing (use an annotation).","Don't place plain values, lambdas, or other constructs as class attributes in a TypedColumns subclass.","Add a test asserting every non-annotation attribute is an instance of Column."],"tags":["sqlalchemy","typed-columns","column","argument-error"],"analyzedSha":"d9b44cb731bd27e6e82c99a3c0fb598214e8e7ff","analyzedAt":"2026-08-01T17:20:52.075Z","schemaVersion":2}