lfnovo/open-notebook · error · RuntimeError
Failed to create record
Error message
Failed to create record
What it means
repo_create() wraps record creation; RuntimeError escapes with its original message (logged), while any other exception is masked as a generic RuntimeError('Failed to create record') with the real cause only in logs. The underlying failure is almost always a SurrealQL/schema issue: missing table, schema validation, duplicate unique key, or serialization of an unsupported field type.
Source
Thrown at open_notebook/database/repository.py:139
async def repo_create(table: str, data: Dict[str, Any]) -> Dict[str, Any]:
"""Create a new record in the specified table"""
# Remove 'id' attribute if it exists in data
data.pop("id", None)
data["created"] = datetime.now(timezone.utc)
data["updated"] = datetime.now(timezone.utc)
try:
async with db_connection() as connection:
result = parse_record_ids(await connection.insert(table, data))
# SurrealDB may return a string error message instead of the expected record
if isinstance(result, str):
raise RuntimeError(result)
return result
except RuntimeError as e:
logger.error(str(e))
raise
except Exception as e:
logger.exception(e)
raise RuntimeError("Failed to create record")
async def repo_relate(
source: Union[str, RecordID],
relationship: str,
target: Union[str, RecordID],
data: Optional[Dict[str, Any]] = None,
) -> List[Dict[str, Any]]:
"""Create a relationship between two records with optional data"""
if data is None:
data = {}
# relationship is an edge-table name, not a record value, so it can't be
# bound as a query parameter; validate it against an identifier allowlist
# instead of trusting the caller. source/target are always bound.
_ensure_safe_identifier(relationship, "relationship")
query = f"RELATE $source->{relationship}->$target CONTENT $data;"
# logger.debug(f"Relate query: {query}")
View on GitHub (pinned to a7de90d38a)
Solutions
- Check the API/worker logs — logger.exception printed the real underlying exception just before this re-raise
- Confirm schema migrations ran (restart make api and read startup logs)
- Verify the target table exists in the expected namespace/database and the payload uses JSON-primitive values (isoformat dates, str ids)
- If a unique index exists, check for a duplicate record before create
Defensive patterns
Strategy: try-catch
Validate before calling
rows = await repo_query(f"SELECT id FROM {table} LIMIT 1")
if not rows:
logger.warning('table %s may not exist yet', table) Try / catch
try:
rec = await repo_create(table, data)
except RuntimeError as e:
logger.exception('create failed for %s', table)
raise HTTPException(500, 'Failed to create record') from e Prevention
- Always inspect server logs — the true cause is logged before the generic re-raise
- Keep model field types aligned with DB schema via migrations
- Serialize dates/enums to JSON primitives before create
When it happens
Trigger: Creating a record for a table that doesn't exist yet (migrations not run); inserting a field value SurrealDB can't store (e.g. datetime without isoformat, custom objects); violating a unique index; record data containing RecordID strings in a field defined with a different type in schema.
Common situations: API started against a fresh database before migrations; schema drift after model changes (new required field not in DB schema); passing enums or Python objects instead of primitives; namespace/database mismatch so the table lives elsewhere.
Related errors
- Failed to update record: {str(e)}
- Search failed: {str(e)}
- Failed to load default models configuration
- Failed to delete record: {str(e)}
- Error fetching all {cls.table_name}: {str(e)}
AI-assisted analysis of lfnovo/open-notebook@a7de90d38a (2026-08-27).
Data as JSON: /api/errors/11a11252fa00b4e6.
Report an issue: GitHub.