lfnovo/open-notebook · error · HTTPException

Failed to fetch episode profiles

Error message

Failed to fetch episode profiles

What it means

Generic 500 raised when listing episode profiles fails unexpectedly (non-OpenNotebookError exception). The real cause is logged with the profile-fetch context.

Solutions

  1. Check API logs for the logged exception detail
  2. Confirm SurrealDB is running and reachable (make status)
  3. Restart the API so migrations re-run and connections refresh
  4. If a specific record fails to deserialize, inspect/repair it in the DB
Defensive patterns

Strategy: retry

Try / catch

try:
    profiles = await client.get("/api/episode-profiles")
except httpx.HTTPStatusError as e:
    if e.response.status_code >= 500:
        await wait_for_api_healthy()
        profiles = await client.get("/api/episode-profiles")
    else:
        raise

Prevention

When it happens

Trigger: GET /api/episode-profiles failing at the DB layer — SurrealDB unreachable, auth failure, or a deserialization problem turning malformed rows into EpisodeProfile objects.

Common situations: Database not started (make database), SurrealDB restarted without the API noticing, schema migration left half-applied, corrupted records.

Related errors


AI-assisted analysis of lfnovo/open-notebook@a7de90d38a (2026-08-27). Data as JSON: /api/errors/a0ac8f3a21af7ce2. Report an issue: GitHub.

Appendix: source

Thrown at api/routers/episode_profiles.py:93

@router.get("/episode-profiles", response_model=List[EpisodeProfileResponse])
async def list_episode_profiles():
    """List all available episode profiles"""
    try:
        profiles = await EpisodeProfile.get_all(order_by="name asc")
        speaker_names = await _speaker_names_by_id()
        return [
            _profile_to_response(
                p, speaker_names.get(p.speaker_config) if p.speaker_config else None
            )
            for p in profiles
        ]
    except HTTPException:
        raise
    except OpenNotebookError:
        raise
    except Exception as e:
        logger.error(f"Failed to fetch episode profiles: {e}")
        raise HTTPException(
            status_code=500, detail="Failed to fetch episode profiles"
        )


@router.get("/episode-profiles/{profile_name}", response_model=EpisodeProfileResponse)
async def get_episode_profile(profile_name: str):
    """Get a specific episode profile by name"""
    try:
        profile = await EpisodeProfile.get_by_name(profile_name)

        if not profile:
            raise HTTPException(
                status_code=404, detail=f"Episode profile '{profile_name}' not found"
            )

        return _profile_to_response(
            profile, await _speaker_name_for(profile.speaker_config)
        )

View on GitHub (pinned to a7de90d38a)