lfnovo/open-notebook · critical · DatabaseOperationError
Failed to delete {self.__class__.table_name}
Error message
Failed to delete {self.__class__.table_name} What it means
delete() wraps repo_delete in try/except and converts any failure into DatabaseOperationError('Failed to delete {table}'). The original error is logged (with the record id) but not attached to the raised message, so logs are the place to find the root cause.
Source
Thrown at open_notebook/domain/base.py:215
def _prepare_save_data(self) -> Dict[str, Any]:
data = self.model_dump()
return {
key: value
for key, value in data.items()
if value is not None or key in self.__class__.nullable_fields
}
async def delete(self) -> bool:
if self.id is None:
raise InvalidInputError("Cannot delete object without an ID")
try:
logger.debug(f"Deleting record with id {self.id}")
return await repo_delete(self.id)
except Exception as e:
logger.error(
f"Error deleting {self.__class__.table_name} with id {self.id}: {str(e)}"
)
raise DatabaseOperationError(
f"Failed to delete {self.__class__.table_name}"
)
async def relate(
self, relationship: str, target_id: str, data: Optional[Dict] = {}
) -> Any:
if not relationship or not target_id or not self.id:
raise InvalidInputError("Relationship and target ID must be provided")
try:
return await repo_relate(
source=self.id, relationship=relationship, target=target_id, data=data
)
except Exception as e:
logger.error(f"Error creating relationship: {str(e)}")
logger.exception(e)
raise DatabaseOperationError(e)
@field_validator("created", "updated", mode="before")View on GitHub (pinned to a7de90d38a)
Solutions
- Check the API logs for the 'Error deleting ...' line to get the underlying cause
- Verify SurrealDB connectivity and retry — transient failures often clear
- Catch DatabaseOperationError in the endpoint and return 503 with a retry hint to the client
- If 'already gone' races are common, treat subsequent NotFoundError on re-check as success (idempotent delete)
Example fix
# before
await note.delete() # unhandled
# after
from open_notebook.domain.errors import DatabaseOperationError
try:
await note.delete()
except DatabaseOperationError:
raise HTTPException(status_code=503, detail="Delete failed, retry shortly") Defensive patterns
Strategy: retry
Try / catch
from open_notebook.domain.errors import DatabaseOperationError, NotFoundError
try:
await note.delete()
except DatabaseOperationError:
try:
await Note.get(note.id) # idempotency check
except NotFoundError:
pass # already deleted; treat as success
else:
raise HTTPException(status_code=503, detail="Delete failed, retry") Prevention
- Make delete endpoints idempotent to tolerate already-deleted races
- Check logs for 'Error deleting {table}' lines to find root causes
- Surface retryable 503s to the client instead of silent failures
When it happens
Trigger: SurrealDB unreachable during delete, record already deleted server-side causing an error path in the driver, permission failures, or graph-relate edges blocking removal. Logged line 'Error deleting {table} with id ...' carries the details.
Common situations: DB tier down when a user hits delete; network blip between API and SurrealDB; deletion racing with another process that already removed the record.
Related errors
- Failed to delete record: {str(e)}
- Error fetching all {cls.table_name}: {str(e)}
- Error saving record: {e}
- Error deleting session: {str(e)}
- Failed to delete episode
AI-assisted analysis of lfnovo/open-notebook@a7de90d38a (2026-08-27).
Data as JSON: /api/errors/188b312d9d70c676.
Report an issue: GitHub.