Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion livekit-plugins/livekit-plugins-gnani/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ classifiers = [
]
dependencies = [
"livekit-agents[codecs]>=1.5.14",
"websockets>=13.1,<16.0",
"websockets>=16,<16.1",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

πŸ”΄ uv.lock not updated after websockets version bump β€” lock file is stale and inconsistent

The pyproject.toml was changed to require websockets>=16,<16.1, but the shared uv.lock file was not regenerated. The lock file still resolves websockets to version 15.0.1 and records the old specifier >=13.1,<16.0 for livekit-plugins-gnani. This means uv sync will detect a stale lock and fail (or silently use the wrong version), since 15.0.1 does not satisfy >=16,<16.1.

Stale lock file metadata

In uv.lock, the gnani entry still reads:

[package.metadata]
requires-dist = [
    { name = "websockets", specifier = ">=13.1,<16.0" },
]

And websockets is resolved globally to 15.0.1, which is incompatible with the new >=16,<16.1 requirement.

Prompt for agents
The pyproject.toml was updated to require websockets>=16,<16.1 but the root uv.lock was not regenerated. The lock file still resolves websockets to 15.0.1 and records the old specifier >=13.1,<16.0 for livekit-plugins-gnani. Run `uv lock` from the repository root to regenerate the lock file. Note that since this is a uv workspace with a single lock file, upgrading websockets to 16.x will affect all workspace members that depend on websockets (e.g. livekit-plugins-phonic, google-genai, fal-client, speechmatics-rt). Verify that all those packages are compatible with websockets 16.x before merging.
Open in Devin Review

Was this helpful? React with πŸ‘ or πŸ‘Ž to provide feedback.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

πŸ”΄ websockets 16 removes websockets.exceptions attribute access, breaking all except clauses

The dependency is bumped to websockets>=16,<16.1, but in websockets 16.0, websockets.exceptions is no longer auto-loaded as an attribute of the websockets module after a bare import websockets. The gnani code does exactly that β€” import websockets in each _run method, then catches websockets.exceptions.ConnectionClosed in except clauses at stt.py:347, tts.py:472, and tts.py:577. In websockets 16, evaluating websockets.exceptions.ConnectionClosed in the except clause raises AttributeError. Per Python semantics, when an except clause's expression itself raises an exception, the remaining except clauses in the same try block are not evaluated β€” so the fallback except Exception handler won't catch it either. This means any ConnectionClosed from the server will surface as an unhandled AttributeError instead of being gracefully wrapped in APIConnectionError.

Verification showing the breakage with websockets 16.0

import websockets; websockets.exceptions β†’ AttributeError: module 'websockets' has no attribute 'exceptions'

import websockets.exceptions; websockets.exceptions.ConnectionClosed β†’ works fine

The fix is to add import websockets.exceptions (or from websockets.exceptions import ConnectionClosed) in each of the three _run methods alongside the existing import websockets.

Prompt for agents
The websockets dependency was bumped from >=13.1,<16.0 to >=16,<16.1. In websockets 16.0, the websockets.exceptions submodule is no longer auto-loaded when you do import websockets. The gnani plugin code catches websockets.exceptions.ConnectionClosed in three places after only doing import websockets:

1. livekit/plugins/gnani/stt.py line 303 does import websockets, then line 347 catches websockets.exceptions.ConnectionClosed
2. livekit/plugins/gnani/tts.py line 417 does import websockets, then line 472 catches websockets.exceptions.ConnectionClosed
3. livekit/plugins/gnani/tts.py line 506 does import websockets, then line 577 catches websockets.exceptions.ConnectionClosed

In all three _run methods, add import websockets.exceptions alongside the existing import websockets. Alternatively, change the except clauses to use a directly imported ConnectionClosed class via from websockets.exceptions import ConnectionClosed at the top of the file.
Open in Devin Review

Was this helpful? React with πŸ‘ or πŸ‘Ž to provide feedback.

]

[project.urls]
Expand Down
Loading