{"record":{"id":"490882eac6071d0b","repo":"lfnovo/open-notebook","slug":"episode-profile-profile-name-not-found","errorCode":null,"errorMessage":"Episode profile '{profile_name}' not found","messagePattern":"Episode profile '(.+?)' not found","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"warning","filePath":"api/routers/episode_profiles.py","lineNumber":105,"sourceCode":"    except HTTPException:\n        raise\n    except OpenNotebookError:\n        raise\n    except Exception as e:\n        logger.error(f\"Failed to fetch episode profiles: {e}\")\n        raise HTTPException(\n            status_code=500, detail=\"Failed to fetch episode profiles\"\n        )\n\n\n@router.get(\"/episode-profiles/{profile_name}\", response_model=EpisodeProfileResponse)\nasync def get_episode_profile(profile_name: str):\n    \"\"\"Get a specific episode profile by name\"\"\"\n    try:\n        profile = await EpisodeProfile.get_by_name(profile_name)\n\n        if not profile:\n            raise HTTPException(\n                status_code=404, detail=f\"Episode profile '{profile_name}' not found\"\n            )\n\n        return _profile_to_response(\n            profile, await _speaker_name_for(profile.speaker_config)\n        )\n\n    except HTTPException:\n        raise\n    except OpenNotebookError:\n        raise\n    except Exception as e:\n        logger.error(f\"Failed to fetch episode profile '{profile_name}': {e}\")\n        raise HTTPException(\n            status_code=500, detail=\"Failed to fetch episode profile\"\n        )\n\n","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/lfnovo/open-notebook/blob/a7de90d38aaf18ee85fd661854d35c11e44613e2/api/routers/episode_profiles.py#L87-L123","documentation":"HTTP 404 from GET /api/episode-profiles/{profile_name} when EpisodeProfile.get_by_name finds no profile with that exact name.","triggerScenarios":"Requesting a profile name that doesn't exist, differs by case/whitespace, or was renamed/deleted concurrently.","commonSituations":"Stale frontend dropdown after another user renamed/deleted a profile; URL-encoding issues turning spaces into '+' or %20 mismatches; environment differences between dev and prod databases.","solutions":["GET /api/episode-profiles to see actual available names","Check for exact case/whitespace/URL-encoding mismatches in the name","If deleted/renamed, update the client to use the current name","Avoid hardcoding profile names; look them up dynamically"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"names = {p[\"name\"] for p in (await client.get(\"/api/episode-profiles\")).json()}\nif profile_name not in names:\n    profile_name = next(iter(names))  # or show a picker","typeGuard":"def profile_exists(name: str, profiles: list[dict]) -> bool:\n    return any(p[\"name\"] == name for p in profiles)","tryCatchPattern":"try:\n    profile = await client.get(f\"/api/episode-profiles/{quote(profile_name)}\")\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code == 404:\n        await refresh_profile_list()  # stale reference; reload\n    else:\n        raise","preventionTips":["URL-encode profile names containing spaces or special characters","Don't hardcode profile names — fetch the list at runtime","Refresh lists after rename/delete operations"],"tags":["http-404","not-found","episode-profile"],"backgroundTag":"resource-not-found","analyzedSha":"a7de90d38aaf18ee85fd661854d35c11e44613e2","analyzedAt":"2026-08-27T02:39:58.166Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}