{"record":{"id":"325ebea79abba1a7","repo":"lfnovo/open-notebook","slug":"failed-to-update-episode-profile","errorCode":null,"errorMessage":"Failed to update episode profile","messagePattern":"Failed to update episode profile","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"api/routers/episode_profiles.py","lineNumber":209,"sourceCode":"        if \"speaker_config\" in update_data:\n            speaker = await _resolve_speaker_config(update_data[\"speaker_config\"])\n            update_data[\"speaker_config\"] = str(speaker.id)\n            speaker_name = speaker.name\n        for field, value in update_data.items():\n            setattr(profile, field, value)\n\n        await profile.save()\n        if speaker_name is None:\n            speaker_name = await _speaker_name_for(profile.speaker_config)\n        return _profile_to_response(profile, speaker_name)\n\n    except HTTPException:\n        raise\n    except OpenNotebookError:\n        raise\n    except Exception as e:\n        logger.error(f\"Failed to update episode profile: {e}\")\n        raise HTTPException(\n            status_code=500, detail=\"Failed to update episode profile\"\n        )\n\n\n@router.delete(\"/episode-profiles/{profile_id}\")\nasync def delete_episode_profile(profile_id: str):\n    \"\"\"Delete an episode profile\"\"\"\n    try:\n        profile = await EpisodeProfile.get(profile_id)\n\n        if not profile:\n            raise HTTPException(\n                status_code=404, detail=f\"Episode profile '{profile_id}' not found\"\n            )\n\n        await profile.delete()\n\n        return {\"message\": \"Episode profile deleted successfully\"}","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/lfnovo/open-notebook/blob/a7de90d38aaf18ee85fd661854d35c11e44613e2/api/routers/episode_profiles.py#L191-L227","documentation":"Generic 500 raised when updating an episode profile fails unexpectedly — typically during db.save() or while re-resolving speaker_config after the update.","triggerScenarios":"PUT with speaker_config that becomes invalid mid-update, DB connectivity failure during save, or model validation errors not covered by InvalidInputError.","commonSituations":"Concurrent update/delete races, DB schema drift, speaker profile deleted between the resolve check and the save.","solutions":["Check the log line 'Failed to update episode profile' for the traceback","Validate speaker_config against current SpeakerProfile records before retrying","Confirm DB health and retry the update","Reload the profile (GET) and reapply the edit to avoid stale-state conflicts"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"current = await client.get(f\"/api/episode-profiles/{profile_id}\")\nif current.status_code == 404:\n    raise FileNotFoundError(profile_id)  # fail fast before building payload","typeGuard":null,"tryCatchPattern":"try:\n    await client.put(f\"/api/episode-profiles/{profile_id}\", json=payload)\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code >= 500:\n        await asyncio.sleep(1)\n        return await client.put(f\"/api/episode-profiles/{profile_id}\", json=payload)\n    raise","preventionTips":["Validate speaker_config before update (see error 62)","Re-read the profile before saving edits to catch races","Check API logs for the exact traceback"],"tags":["http-500","internal-error","episode-profile","update"],"backgroundTag":"internal-server-error","analyzedSha":"a7de90d38aaf18ee85fd661854d35c11e44613e2","analyzedAt":"2026-08-27T02:39:58.166Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}