lfnovo/open-notebook · error · HTTPException

Failed to create episode profile

Error message

Failed to create episode profile

What it means

Generic 500 raised when creating an episode profile fails unexpectedly — after the HTTP/NotFound/InvalidInput/OpenNotebookError paths were excluded. Typically a save or uniqueness failure at the DB layer.

Source

Thrown at api/routers/episode_profiles.py:173

            speaker_config=str(speaker.id),
            outline_llm=profile_data.outline_llm,
            transcript_llm=profile_data.transcript_llm,
            language=profile_data.language,
            default_briefing=profile_data.default_briefing,
            num_segments=profile_data.num_segments,
            max_tokens=profile_data.max_tokens,
        )

        await profile.save()
        return _profile_to_response(profile, speaker.name)

    except HTTPException:
        raise
    except OpenNotebookError:
        raise
    except Exception as e:
        logger.error(f"Failed to create episode profile: {e}")
        raise HTTPException(
            status_code=500, detail="Failed to create episode profile"
        )


@router.put("/episode-profiles/{profile_id}", response_model=EpisodeProfileResponse)
async def update_episode_profile(profile_id: str, profile_data: EpisodeProfileCreate):
    """Update an existing episode profile"""
    try:
        profile = await EpisodeProfile.get(profile_id)

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

        update_data = profile_data.model_dump(exclude_unset=True)
        speaker_name: Optional[str] = None
        if "speaker_config" in update_data:

View on GitHub (pinned to a7de90d38a)

Solutions

  1. Check logs for the exact exception during create
  2. If it's a duplicate name, GET the list and pick a unique name
  3. Verify SurrealDB health and retry
  4. For race conditions on unique names, retry with a suffixed name or add app-level uniqueness enforcement
Defensive patterns

Strategy: try-catch

Validate before calling

existing = {p["name"] for p in (await client.get("/api/episode-profiles")).json()}
if payload["name"] in existing:
    payload["name"] = f"{payload['name']} ({uuid.uuid4().hex[:4]})"

Try / catch

try:
    resp = await client.post("/api/episode-profiles", json=payload)
except httpx.HTTPStatusError as e:
    if e.response.status_code >= 500:
        # check logs; likely name collision or DB issue — retry with unique name
        payload["name"] += f" {uuid.uuid4().hex[:4]}"
        resp = await client.post("/api/episode-profiles", json=payload)
    raise

Prevention

When it happens

Trigger: POST /api/episode-profiles failing during db.save() — DB unreachable, unique-name constraint violation surfaced as a raw driver error, or invalid model state.

Common situations: Duplicate profile name that isn't caught by the app-level check (race between two concurrent creates), DB schema mismatch after migration, DB outage.

Related errors


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