Skip to content

Stop the OMIT sentinel from reaching the realtime TTS connection - #858

Merged
PaulAsjes merged 1 commit into
elevenlabs:mainfrom
Kayvan-Zahiri:fix/realtime-tts-omit-sentinel
Sep 3, 2026
Merged

PaulAsjes merged 1 commit into
elevenlabs:mainfrom
Kayvan-Zahiri:fix/realtime-tts-omit-sentinel

Conversation

@Kayvan-Zahiri

Copy link
Copy Markdown
Contributor

convert_realtime raises AttributeError: 'ellipsis' object has no attribute 'dict' at its documented default, before it sends any text. model_id and voice_settings both default to OMIT, which is Ellipsis. Line 115 is voice_settings.dict() if voice_settings else None, and Ellipsis is truthy, so .dict() is called on the sentinel.

The same sentinel reaches the URL. model_id goes straight into build_ws_url, where urlencode stringifies it, so a caller who passes voice_settings but omits model_id connects to stream-input?model_id=Ellipsis&output_format=mp3_44100_128 instead of letting the server apply its default. This predates the build_ws_url refactor in #780; the old f-string produced the same query string.

realtime/scribe.py and conversational_ai/conversation.py both build their params conditionally. This does the same, reusing the remove_none_from_dict already imported in this file.

Four of the six added tests fail on main. The suite goes from 189 to 195 passed, with the same 16 live-API failures on either side, and mypy is clean. Both files touched are listed in .fernignore. I left the pre-existing ruff import-order warning in this file alone rather than bury a six line fix.

…ction

model_id and voice_settings both default to OMIT, which is Ellipsis.
Ellipsis is truthy, so `voice_settings.dict() if voice_settings else None`
called .dict() on the sentinel and raised AttributeError at the documented
default call. model_id was passed straight into build_ws_url, where
urlencode stringified it into model_id=Ellipsis.

Normalize both sentinels to None and filter the query params with the
remove_none_from_dict already imported in this file, matching how
realtime/scribe.py and conversational_ai/conversation.py build theirs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@cursor

cursor Bot commented Sep 2, 2026 •

Copy link
Copy Markdown

PR Summary

Low Risk
Small, targeted fix in realtime TTS client wiring with regression tests; no auth or data-model changes.

Overview
Fixes convert_realtime when optional args use the default OMIT sentinel (Ellipsis), which was truthy and broke .dict() on voice_settings, and could put model_id=Ellipsis on the WebSocket URL when callers omitted model_id.

Before opening the connection, model_id and voice_settings are normalized from OMIT to None, and query params for build_ws_url go through remove_none_from_dict so omitted model_id is not encoded. Explicit model_id, voice_settings, and default output_format behavior stay the same.

Adds tests/test_realtime_tts_params.py with mocked WebSocket tests for URL query strings and the first JSON frame.

Reviewed by Cursor Bugbot for commit b93c137. Bugbot is set up for automated code reviews on this repo. Configure here.

@PaulAsjes

Copy link
Copy Markdown
Collaborator

Thanks for the contribution, but the file you've edited is autogenerated so your changes will be overwritten the next time we generate the SDKs.

Instead this needs to be fixed upstream in the generator, so I'm closing this for now.

@PaulAsjes PaulAsjes closed this Sep 2, 2026
@Kayvan-Zahiri

Copy link
Copy Markdown
Contributor Author

Thanks for taking a look, and no problem either way. I think this one may be a false alarm
though, so flagging it in case it's worth a second look.

src/elevenlabs/realtime_tts.py is listed in .fernignore, under "Ignore manually created
SDK wrappers", and tests/ is ignored too, so both files in this PR are excluded from
regeneration. AGENTS.md says "Only files listed in .fernignore are hand-maintained and
safe to edit", which is how I picked it.

The file does still carry the "auto-generated by Fern" header, which is what I suspect
prompted the close. That header looks stale rather than accurate:

So a human edit to this file has already survived a regeneration cycle.

Happy to be wrong here. If the OMIT handling really does originate in the generator I'll
leave it alone, and if it would help I can open an issue describing the bug instead so it
is tracked somewhere useful.

@PaulAsjes PaulAsjes reopened this Sep 3, 2026
@PaulAsjes

Copy link
Copy Markdown
Collaborator

You're absolutely right, sorry about that. Will look at this again in more detail.

@PaulAsjes PaulAsjes left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@PaulAsjes
PaulAsjes merged commit 2a3eb71 into elevenlabs:main Sep 3, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants