{"record":{"id":"188b312d9d70c676","repo":"lfnovo/open-notebook","slug":"failed-to-delete-self-class-table-name","errorCode":null,"errorMessage":"Failed to delete {self.__class__.table_name}","messagePattern":"Failed to delete (.+?)","errorType":"exception","errorClass":"DatabaseOperationError","httpStatus":null,"severity":"critical","filePath":"open_notebook/domain/base.py","lineNumber":215,"sourceCode":"    def _prepare_save_data(self) -> Dict[str, Any]:\n        data = self.model_dump()\n        return {\n            key: value\n            for key, value in data.items()\n            if value is not None or key in self.__class__.nullable_fields\n        }\n\n    async def delete(self) -> bool:\n        if self.id is None:\n            raise InvalidInputError(\"Cannot delete object without an ID\")\n        try:\n            logger.debug(f\"Deleting record with id {self.id}\")\n            return await repo_delete(self.id)\n        except Exception as e:\n            logger.error(\n                f\"Error deleting {self.__class__.table_name} with id {self.id}: {str(e)}\"\n            )\n            raise DatabaseOperationError(\n                f\"Failed to delete {self.__class__.table_name}\"\n            )\n\n    async def relate(\n        self, relationship: str, target_id: str, data: Optional[Dict] = {}\n    ) -> Any:\n        if not relationship or not target_id or not self.id:\n            raise InvalidInputError(\"Relationship and target ID must be provided\")\n        try:\n            return await repo_relate(\n                source=self.id, relationship=relationship, target=target_id, data=data\n            )\n        except Exception as e:\n            logger.error(f\"Error creating relationship: {str(e)}\")\n            logger.exception(e)\n            raise DatabaseOperationError(e)\n\n    @field_validator(\"created\", \"updated\", mode=\"before\")","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/lfnovo/open-notebook/blob/a7de90d38aaf18ee85fd661854d35c11e44613e2/open_notebook/domain/base.py#L197-L233","documentation":"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.","triggerScenarios":"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.","commonSituations":"DB tier down when a user hits delete; network blip between API and SurrealDB; deletion racing with another process that already removed the record.","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)"],"exampleFix":"# before\nawait note.delete()  # unhandled\n\n# after\nfrom open_notebook.domain.errors import DatabaseOperationError\ntry:\n    await note.delete()\nexcept DatabaseOperationError:\n    raise HTTPException(status_code=503, detail=\"Delete failed, retry shortly\")","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"from open_notebook.domain.errors import DatabaseOperationError, NotFoundError\ntry:\n    await note.delete()\nexcept DatabaseOperationError:\n    try:\n        await Note.get(note.id)  # idempotency check\n    except NotFoundError:\n        pass  # already deleted; treat as success\n    else:\n        raise HTTPException(status_code=503, detail=\"Delete failed, retry\")","preventionTips":["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"],"tags":["database","delete","surrealdb","open-notebook"],"backgroundTag":"database-delete-failed","analyzedSha":"a7de90d38aaf18ee85fd661854d35c11e44613e2","analyzedAt":"2026-08-27T02:39:58.166Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}