lfnovo/open-notebook · error · InvalidInputError
No class found for table {table_name}
Error message
No class found for table {table_name} What it means
When get(id) is called and the table name embedded in the record id (the part before the first ':') does not match the calling class, the method searches all registered ObjectModel subclasses via _get_class_by_table_name. If no subclass declares that table_name, there is no model to deserialize the row into, so it raises InvalidInputError.
Source
Thrown at open_notebook/domain/base.py:119
logger.exception(e)
raise DatabaseOperationError(e)
@classmethod
async def get(cls: Type[T], id: str) -> T:
if not id:
raise InvalidInputError("ID cannot be empty")
try:
# Get the table name from the ID (everything before the first colon)
table_name = id.split(":")[0] if ":" in id else id
# If we're calling from a specific subclass and IDs match, use that class
if cls.table_name and cls.table_name == table_name:
target_class: Type[T] = cls
else:
# Otherwise, find the appropriate subclass based on table_name
found_class = cls._get_class_by_table_name(table_name)
if not found_class:
raise InvalidInputError(f"No class found for table {table_name}")
target_class = cast(Type[T], found_class)
result = await repo_query("SELECT * FROM $id", {"id": ensure_record_id(id)})
if result:
return target_class(**result[0])
else:
raise NotFoundError(f"{table_name} with id {id} not found")
except Exception as e:
logger.error(f"Error fetching object with id {id}: {str(e)}")
logger.exception(e)
raise NotFoundError(f"Object with id {id} not found - {str(e)}")
@classmethod
def _get_class_by_table_name(cls, table_name: str) -> Optional[Type["ObjectModel"]]:
"""Find the appropriate subclass based on table_name."""
def get_all_subclasses(c: Type["ObjectModel"]) -> List[Type["ObjectModel"]]:
all_subclasses: List[Type["ObjectModel"]] = []View on GitHub (pinned to a7de90d38a)
Solutions
- Check the id's table prefix matches a real model (everything before the first ':')
- Ensure the model module is imported so the subclass is discoverable
- If the table was renamed, update the stored ids or add a compatibility mapping
- Prefer calling get() on the specific class whose table matches the id
Example fix
# before
obj = await ObjectModel.get(f"{table}:{rid}") # table may be unknown
# after
from open_notebook.domain.model import Note
obj = await Note.get(f"note:{rid}") Defensive patterns
Strategy: type-guard
Validate before calling
table = rid.split(":", 1)[0]
if table not in KNOWN_TABLES: # {'note', 'source', ...}
raise HTTPException(status_code=400, detail=f"Unknown table '{table}'") Type guard
KNOWN = {c.table_name for c in ObjectModel.__subclasses__()} # after imports
def table_is_registered(rid: str) -> bool:
return rid.split(":", 1)[0] in {c.table_name for c in all_subclasses(ObjectModel)} Try / catch
from open_notebook.domain.errors import InvalidInputError
try:
obj = await ObjectModel.get(rid)
except InvalidInputError as e:
raise HTTPException(status_code=400, detail=str(e)) Prevention
- Construct record ids from the model class's table_name, not string literals
- Keep a single registry/mapping of table names to model classes
- Import all model modules at startup so subclass discovery works
When it happens
Trigger: await ObjectModel.get('sometable:abc123') where no model subclass has table_name='sometable'; typo'd table prefix in an id string; a model class that exists but was never imported (so not in the subclass registry).
Common situations: Ids constructed by string concatenation with a wrong table prefix; model module not imported anywhere so __subclasses__ never includes it; renamed table_name in a model while old ids still circulate in stored data or queues.
Related errors
- {table_name} with id {id} not found
- Failed to delete record: {str(e)}
- Error fetching all {cls.table_name}: {str(e)}
- Object with id {id} not found - {str(e)}
- Error saving record: {e}
AI-assisted analysis of lfnovo/open-notebook@a7de90d38a (2026-08-27).
Data as JSON: /api/errors/410548bcad8df22f.
Report an issue: GitHub.