lfnovo/open-notebook · error · InvalidInputError
Speaker profile '{value}' not found
Error message
Speaker profile '{value}' not found What it means
InvalidInputError (mapped to HTTP 400) raised when creating/updating an episode profile and the provided speaker_config cannot be resolved to a SpeakerProfile record — it is neither a valid record ID nor a known profile name.
Source
Thrown at api/routers/episode_profiles.py:71
name=profile.name,
description=profile.description or "",
speaker_config=profile.speaker_config,
speaker_config_name=speaker_name,
outline_llm=profile.outline_llm,
transcript_llm=profile.transcript_llm,
language=profile.language,
default_briefing=profile.default_briefing,
num_segments=profile.num_segments,
max_tokens=profile.max_tokens,
)
async def _resolve_speaker_config(value: str) -> SpeakerProfile:
"""Resolve an incoming speaker_config (record ID, or name for backward
compatibility) to the referenced SpeakerProfile."""
speaker = await SpeakerProfile.resolve(value)
if not speaker:
raise InvalidInputError(f"Speaker profile '{value}' not found")
return speaker
@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:View on GitHub (pinned to a7de90d38a)
Solutions
- GET /api/speaker-profiles to list valid ids/names and use one of them
- If resolving by name, ensure the name matches exactly (case/whitespace)
- If the speaker profile was deleted, recreate it or clear speaker_config
- Prefer the record ID over the name for stability
Example fix
// before
{"name": "podcast", "speaker_config": "Default Speaker"}
// after
{"name": "podcast", "speaker_config": "speaker_profile:abc123"} Defensive patterns
Strategy: validation
Validate before calling
profiles = (await client.get("/api/speaker-profiles")).json()
valid = {p["id"] for p in profiles} | {p["name"] for p in profiles}
if payload.get("speaker_config") not in valid:
payload["speaker_config"] = profiles[0]["id"] # or prompt the user Type guard
def is_valid_speaker_ref(value: str, profiles: list[dict]) -> bool:
return value in {p["id"] for p in profiles} | {p["name"] for p in profiles} Try / catch
try:
await create_episode_profile(payload)
except HTTPError as e:
if e.response.status_code == 400 and "not found" in e.response.text:
# refresh speaker list and re-submit with a valid id
... Prevention
- Reference speaker profiles by record id, not display name
- Refresh the speaker-profile list before showing profile forms
- Handle deletion of speaker profiles by cleaning up episode profiles that reference them
When it happens
Trigger: POST or PUT /api/episode-profiles with speaker_config set to a deleted SpeakerProfile id, a misspelled name, or an id from a different environment/database.
Common situations: Speaker profile deleted after the frontend cached its name; copying request bodies between environments; using a display name when the record was stored under a different name after SpeakerProfile.resolve semantics changed.
Related errors
- No embedding model configured. Please configure one in the M
- Item type must be either 'source' or 'note'
- Failed to fetch episode profiles
- Episode profile '{profile_name}' not found
- Failed to fetch episode profile
AI-assisted analysis of lfnovo/open-notebook@a7de90d38a (2026-08-27).
Data as JSON: /api/errors/f82d08e9ca862de0.
Report an issue: GitHub.