{"record":{"id":"552a085a5982196d","repo":"lfnovo/open-notebook","slug":"get-all-must-be-called-from-a-specific-model-cla","errorCode":null,"errorMessage":"get_all() must be called from a specific model class","messagePattern":"get_all\\(\\) must be called from a specific model class","errorType":"exception","errorClass":"InvalidInputError","httpStatus":400,"severity":"error","filePath":"open_notebook/domain/base.py","lineNumber":81,"sourceCode":"                    raise InvalidInputError(\n                        f\"Invalid order_by clause: '{clause.strip()}'\"\n                    )\n                validated_clauses.append(f\"{parts[0].lower()} {parts[1].lower()}\")\n            else:\n                raise InvalidInputError(f\"Invalid order_by clause: '{clause.strip()}'\")\n\n        return \", \".join(validated_clauses)\n\n    @classmethod\n    async def get_all(cls: Type[T], order_by=None) -> List[T]:\n        try:\n            # If called from a specific subclass, use its table_name\n            if cls.table_name:\n                target_class = cls\n                table_name = cls.table_name\n            else:\n                # This path is taken if called directly from ObjectModel\n                raise InvalidInputError(\n                    \"get_all() must be called from a specific model class\"\n                )\n            if order_by:\n                validated_order_by = cls._validate_order_by(order_by)\n                query = f\"SELECT * FROM {table_name} ORDER BY {validated_order_by}\"\n            else:\n                query = f\"SELECT * FROM {table_name}\"\n\n            result = await repo_query(query)\n            objects = []\n            for obj in result:\n                try:\n                    objects.append(target_class(**obj))\n                except Exception as e:\n                    logger.critical(f\"Error creating object: {str(e)}\")\n\n            return objects\n        except Exception as e:","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/lfnovo/open-notebook/blob/a7de90d38aaf18ee85fd661854d35c11e44613e2/open_notebook/domain/base.py#L63-L99","documentation":"ObjectModel.get_all() resolves the target table from cls.table_name, which is only defined on concrete subclasses. Calling it directly on the base class ObjectModel leaves table_name empty, so there is no table to SELECT from and the method raises InvalidInputError immediately.","triggerScenarios":"await ObjectModel.get_all() or ObjectModel.get_all(order_by='x asc') — any call on the base class rather than a subclass like Note, Source, or Chat.","commonSituations":"Generic/helper code that receives a Type[T] variable typed as ObjectModel and accidentally calls get_all on it; refactoring that loses the concrete class; interactive experimentation importing ObjectModel directly.","solutions":["Call get_all() on the concrete model class (e.g. await Note.get_all())","If using generics, ensure the Type[T] is bound to a subclass with table_name set","Check the model definition to confirm table_name is defined on the subclass"],"exampleFix":"// before\nawait ObjectModel.get_all()\n\n// after\nfrom open_notebook.domain.model import Note\nawait Note.get_all()","handlingStrategy":"type-guard","validationCode":"if not getattr(cls, \"table_name\", None):\n    raise ValueError(\"Call get_all() on a concrete model subclass, not ObjectModel\")","typeGuard":"from open_notebook.domain.base import ObjectModel\nfrom typing import Type, TypeVar\n\ndef is_concrete_model(cls: Type) -> bool:\n    return issubclass(cls, ObjectModel) and bool(getattr(cls, \"table_name\", None))","tryCatchPattern":null,"preventionTips":["Always import and use the specific model class (Note, Source, ...)","In generic helpers, assert the type var is bound to a subclass with table_name set","Lint rule / review check: no direct ObjectModel.get_all calls"],"tags":["open-notebook","base-class-misuse","orm","type-error"],"backgroundTag":"abstract-class-instantiation-error","analyzedSha":"a7de90d38aaf18ee85fd661854d35c11e44613e2","analyzedAt":"2026-08-27T02:39:58.166Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}