HKUDS/DeepTutor · warning · HTTPException
Record not found
Error message
Record not found
What it means
404 raised when notebook_manager.remove_record returns falsy, meaning either the notebook or the record id passed on the path does not exist in the store. Deletion is only attempted after both ids resolve; otherwise the endpoint aborts with 'Record not found'.
Source
Thrown at deeptutor/api/routers/notebook.py:381
)
@router.delete("/{notebook_id}/records/{record_id}")
async def remove_record(notebook_id: str, record_id: str):
"""
Remove record from notebook
Args:
notebook_id: Notebook ID
record_id: Record ID
Returns:
Deletion result
"""
try:
success = notebook_manager.remove_record(notebook_id, record_id)
if not success:
raise HTTPException(status_code=404, detail="Record not found")
return {"success": True, "message": "Record removed successfully"}
except HTTPException:
raise
except NotebookCorruptedError as exc:
raise _unreadable(exc)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.put("/{notebook_id}/records/{record_id}")
async def update_record(notebook_id: str, record_id: str, request: UpdateRecordRequest):
"""Update an existing notebook record in place."""
try:
# Forward only what the client actually sent. Passing every field
# unconditionally would hand `kb_name=None` to the service on every
# request and clear the record's knowledge-base link as a side effect
# of renaming it; the service's sentinel default only works if an
# omitted field never reaches it.View on GitHub (pinned to 3e82f13042)
Solutions
- Re-fetch the notebook's records to get current ids before deleting
- Treat 404 on delete as idempotent success if the record is already gone
- Confirm notebook_id is correct and the notebook still exists
Example fix
// before
await client.delete(f"/notebook/{nb}/records/{rid}") # raises 404
// after
resp = await client.delete(f"/notebook/{nb}/records/{rid}")
if resp.status_code == 404:
pass # already removed; treat as success Defensive patterns
Strategy: try-catch
Validate before calling
resp = await client.get(f"/notebook/{nb}/records")
exists = any(r["id"] == rid for r in resp.json()["records"])
if not exists:
return # already gone Try / catch
resp = await client.delete(f"/notebook/{nb}/records/{rid}")
if resp.status_code == 404:
pass # idempotent delete Prevention
- Treat delete 404 as success for idempotency
- Disable delete buttons after first click to avoid double-submit
- Refresh record lists before destructive actions
When it happens
Trigger: DELETE (or the remove_record route) with a record_id that was already deleted, a notebook_id that doesn't exist, or ids copied from a different environment/data directory.
Common situations: Double-submit of a delete button where the first request already removed the record; UI holding stale record ids after another client removed them; data directory reset between listing and deleting.
Related errors
- Record or target notebook not found
- No fields to update
- t("api.partner_not_found_or_not_running")
- t("api.partner_not_running")
- str(exc)
AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27).
Data as JSON: /api/errors/555efbdda5388bcc.
Report an issue: GitHub.