{"record":{"id":"d1fad036bac39836","repo":"lfnovo/open-notebook","slug":"failed-to-delete-record-str-e","errorCode":null,"errorMessage":"Failed to delete record: {str(e)}","messagePattern":"Failed to delete record: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"open_notebook/database/repository.py","lineNumber":216,"sourceCode":"        query = \"UPDATE $target MERGE $data;\"\n        # logger.debug(f\"Update query: {query}\")\n        result = await repo_query(query, {\"target\": record_id, \"data\": data})\n        # if isinstance(result, list):\n        #     return [_return_data(item) for item in result]\n        return parse_record_ids(result)\n    except Exception as e:\n        raise RuntimeError(f\"Failed to update record: {str(e)}\")\n\n\nasync def repo_delete(record_id: Union[str, RecordID]):\n    \"\"\"Delete a record by record id\"\"\"\n\n    try:\n        async with db_connection() as connection:\n            return await connection.delete(ensure_record_id(record_id))\n    except Exception as e:\n        logger.exception(e)\n        raise RuntimeError(f\"Failed to delete record: {str(e)}\")\n\n\nasync def repo_insert(\n    table: str, data: List[Dict[str, Any]], ignore_duplicates: bool = False\n) -> List[Dict[str, Any]]:\n    \"\"\"Create a new record in the specified table\"\"\"\n    try:\n        async with db_connection() as connection:\n            result = parse_record_ids(await connection.insert(table, data))\n            # SurrealDB may return a string error message instead of the expected records\n            if isinstance(result, str):\n                raise RuntimeError(result)\n            return result\n    except RuntimeError as e:\n        if ignore_duplicates and \"already contains\" in str(e):\n            return []\n        # Log transaction conflicts at debug level (they are expected during concurrent operations)\n        error_str = str(e).lower()","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/lfnovo/open-notebook/blob/a7de90d38aaf18ee85fd661854d35c11e44613e2/open_notebook/database/repository.py#L198-L234","documentation":"repo_delete() calls connection.delete(ensure_record_id(record_id)) and wraps any failure as RuntimeError('Failed to delete record: <cause>'). Typical causes: malformed record id string, the record not existing, or connection/permission errors. The original exception is logged via logger.exception before re-raising.","triggerScenarios":"Passing a plain string like 'note' or 'note:' instead of a valid 'table:id' record id; deleting an already-deleted record (some SurrealDB versions error on missing targets); connection dropped mid-delete; deleting across a namespace where the table doesn't exist.","commonSituations":"Double-delete from UI double-clicks or concurrent requests; frontend sending an unsanitized id; retries after a first successful delete; env pointing at the wrong namespace so nothing matches.","solutions":["Inspect the appended cause and the logged stack trace","Validate the id with ensure_record_id semantics before calling: must be 'table:id' format","Make delete idempotent: check existence first or tolerate 'not found' in the caller","Prevent duplicate delete requests in the UI (disable button after click)"],"exampleFix":"// before\nawait repo_delete(note_id_or_none)\n// after\nfrom surrealdb import RecordID\ntable, _, rid = str(note_id).partition(':')\nassert table and rid, 'expected table:id'\nawait repo_delete(RecordID(table, rid))","handlingStrategy":"try-catch","validationCode":"from open_notebook.database.repository import ensure_record_id\ntry:\n    rid = ensure_record_id(record_id)  # raises on malformed id\nexcept Exception:\n    raise InvalidInputError('expected table:id record id')","typeGuard":"import re\ndef is_record_id(v) -> bool:\n    return isinstance(v, str) and bool(re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*:[^:]+$', v)) or isinstance(v, RecordID)","tryCatchPattern":"try:\n    await repo_delete(record_id)\nexcept RuntimeError as e:\n    if 'not found' in str(e).lower():\n        return  # idempotent delete\n    raise","preventionTips":["Make deletes idempotent — tolerate not-found","Validate 'table:id' format client-side before sending","Disable delete buttons after first click to avoid duplicate requests"],"tags":["database","surrealdb","delete","record-id"],"backgroundTag":"database-delete-failed","analyzedSha":"a7de90d38aaf18ee85fd661854d35c11e44613e2","analyzedAt":"2026-08-27T02:39:58.166Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}