lfnovo/open-notebook · error · InvalidInputError

get_all() must be called from a specific model class

Error message

get_all() must be called from a specific model class

What it means

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.

Source

Thrown at open_notebook/domain/base.py:81

                    raise InvalidInputError(
                        f"Invalid order_by clause: '{clause.strip()}'"
                    )
                validated_clauses.append(f"{parts[0].lower()} {parts[1].lower()}")
            else:
                raise InvalidInputError(f"Invalid order_by clause: '{clause.strip()}'")

        return ", ".join(validated_clauses)

    @classmethod
    async def get_all(cls: Type[T], order_by=None) -> List[T]:
        try:
            # If called from a specific subclass, use its table_name
            if cls.table_name:
                target_class = cls
                table_name = cls.table_name
            else:
                # This path is taken if called directly from ObjectModel
                raise InvalidInputError(
                    "get_all() must be called from a specific model class"
                )
            if order_by:
                validated_order_by = cls._validate_order_by(order_by)
                query = f"SELECT * FROM {table_name} ORDER BY {validated_order_by}"
            else:
                query = f"SELECT * FROM {table_name}"

            result = await repo_query(query)
            objects = []
            for obj in result:
                try:
                    objects.append(target_class(**obj))
                except Exception as e:
                    logger.critical(f"Error creating object: {str(e)}")

            return objects
        except Exception as e:

View on GitHub (pinned to a7de90d38a)

Solutions

  1. Call get_all() on the concrete model class (e.g. await Note.get_all())
  2. If using generics, ensure the Type[T] is bound to a subclass with table_name set
  3. Check the model definition to confirm table_name is defined on the subclass

Example fix

// before
await ObjectModel.get_all()

// after
from open_notebook.domain.model import Note
await Note.get_all()
Defensive patterns

Strategy: type-guard

Validate before calling

if not getattr(cls, "table_name", None):
    raise ValueError("Call get_all() on a concrete model subclass, not ObjectModel")

Type guard

from open_notebook.domain.base import ObjectModel
from typing import Type, TypeVar

def is_concrete_model(cls: Type) -> bool:
    return issubclass(cls, ObjectModel) and bool(getattr(cls, "table_name", None))

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of lfnovo/open-notebook@a7de90d38a (2026-08-27). Data as JSON: /api/errors/552a085a5982196d. Report an issue: GitHub.