{"record":{"id":"d5035966c49b5fc9","repo":"iflytek/astron-agent","slug":"unable-to-inspect-model-model","errorCode":null,"errorMessage":"Unable to inspect model {model}","messagePattern":"Unable to inspect model (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"core/plugin/link/domain/models/utils.py","lineNumber":175,"sourceCode":"        with Session(self.engine) as session:\n            yield session\n\n    def check_table(self, model: type[SQLModel]) -> List[Result]:\n        \"\"\"Check if a table and its columns exist in the database.\n\n        Args:\n            model: SQLModel class to check against database.\n\n        Returns:\n            list[Result]: List of Result objects for table and column checks.\n        \"\"\"\n        results = []\n        inspector = inspect(self.engine)\n\n        # Use SQLAlchemy inspect() to get table name instead of private __tablename__\n        model_inspector = inspect(model)\n        if model_inspector is None:\n            raise ValueError(f\"Unable to inspect model {model}\")\n        table_name = model_inspector.local_table.name\n\n        # Use modern Pydantic v2 model_fields instead of deprecated __fields__\n        expected_columns = list(getattr(model, \"model_fields\", {}).keys())\n        try:\n            available_columns = [\n                col[\"name\"] for col in inspector.get_columns(table_name)\n            ]\n            results.append(Result(name=table_name, type=\"table\", success=True))\n        except sa.exc.NoSuchTableError:\n            logger.error(f\"Missing table: {table_name}\")\n            results.append(Result(name=table_name, type=\"table\", success=False))\n            return results\n\n        for column in expected_columns:\n            if column not in available_columns:\n                logger.error(f\"Missing column: {column} in table {table_name}\")\n                results.append(Result(name=column, type=\"column\", success=False))","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/plugin/link/domain/models/utils.py#L157-L193","documentation":"check_table() uses SQLAlchemy's inspect() on a SQLModel class to discover its mapped table. inspect(model) returns None when the object passed is not a mapped class (no entry in the SQLAlchemy registry), so the guard raises ValueError naming the model. This means the argument is not a valid SQLModel/SQLAlchemy declarative class.","triggerScenarios":"Calling check_table() with a non-mapped object: a plain class not inheriting SQLModel, an instance instead of the class, a model whose mappers were not configured (e.g. SQLModel not imported/registered), or any arbitrary type such as a string or dict.","commonSituations":"Passing an instantiated model (check_table(MyModel())) instead of the class; typos importing the model so the real mapped class never loads; refactoring a model away from SQLModel to a dataclass/pydantic BaseModel while still calling check_table on it; circular imports leaving the model module partially initialized.","solutions":["Pass the model class itself, not an instance: check_table(MyModel), not check_table(MyModel()).","Verify the argument inherits from SQLModel (or has a __tablename__/__mapper__ attribute) and that the module defining it is imported before check_table runs.","If using plain Pydantic models, switch them to SQLModel so SQLAlchemy can map them, or stop calling check_table on unmapped models.","Check for circular imports that prevent the model class from being fully defined/registered."],"exampleFix":"// before\nservice.check_table(item_instance)          # instance, not mapped class\nservice.check_table(SomePlainPydanticModel) # not SQLModel\n// after\nfrom domain.models import Item  # SQLModel subclass, imported for mapper registration\nservice.check_table(Item)       # pass the class","handlingStrategy":"validation","validationCode":"def is_mapped_model(m) -> bool:\n    from sqlmodel import SQLModel\n    return isinstance(m, type) and issubclass(m, SQLModel)\n\nassert is_mapped_model(MyModel), \"pass the SQLModel class, not an instance\"","typeGuard":"def is_sqlmodel_class(obj) -> bool:\n    import inspect as _i\n    from sqlmodel import SQLModel\n    return _i.isclass(obj) and issubclass(obj, SQLModel)","tryCatchPattern":"try:\n    results = service.check_table(model)\nexcept ValueError as e:\n    logger.error(\"check_table needs a mapped SQLModel class: %s\", e)","preventionTips":["Always pass the class, never an instance, to check_table.","Import all model modules before running schema checks so mappers are registered.","Assert issubclass(model, SQLModel) in test fixtures that call check_table."],"tags":["sqlalchemy","orm","invalid-argument"],"backgroundTag":"invalid-argument-value","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}