Skip to content

[fix] bump livekit rtc 1.1.9 → 1.1.13 修 local_track_unpublished KeyError - #1

Closed
YJack0000 wants to merge 1 commit into
pathorsfrom
fix/livekit-rtc-1.1.13-unpublish-keyerror
Closed

[fix] bump livekit rtc 1.1.9 → 1.1.13 修 local_track_unpublished KeyError#1
YJack0000 wants to merge 1 commit into
pathorsfrom
fix/livekit-rtc-1.1.13-unpublish-keyerror

Conversation

@YJack0000

Copy link
Copy Markdown

Fixes the local_track_unpublished KeyError spam in production livekit-agent.
Main-repo tracking issue: pathorsAI/pathors#1274

AS IS

Pin 是 livekit==1.1.9。該版 Room._on_room_eventlocal_track_unpublished
事件做無防護的 dict 查找(rtc/room.py:739):

elif which == "local_track_unpublished":
    sid = event.local_track_unpublished.publication_sid
    lpublication = self.local_participant.track_publications[sid]   # ← KeyError
    self.emit("local_track_unpublished", lpublication)

這跟 LocalParticipant.unpublish_track()rtc/participant.py:777)打架。
unpublish_track 在自己的 FFI response 回來後會先 pop 掉 publication:

cb = await queue.wait_for(lambda e: e.unpublish_track.async_id == resp.unpublish_track.async_id)
...
publication = self._track_publications.pop(track_sid)   # ← 先發生

而 Rust FFI 同時往同一條 event queue 丟一個 local_track_unpublished
RoomEvent。兩者的處理順序不保證:response 先被處理時,RoomEvent 後到,
dict 裡已經沒有那個 sid,_listen_task 就整個 except 起來印 traceback。

生產環境長這樣(每通電話 teardown 都可能出現):

error running user callback for local_track_unpublished: room_handle: 4
local_track_unpublished { publication_sid: "TR_A5W7zQm8FRQAa" }
Traceback (most recent call last):
  File ".../livekit/rtc/room.py", line 682, in _listen_task
    self._on_room_event(event.room_event)
  File ".../livekit/rtc/room.py", line 739, in _on_room_event
    lpublication = self.local_participant.track_publications[sid]
KeyError: 'TR_A5W7zQm8FRQAa'

log 的 "error running user callback" 有誤導性:那是 _listen_task
catch-all wrapper,實際炸掉的是 SDK 自己的 event dispatch,還沒碰到任何
user callback。

觸發點就在這個 repovoice/background_audio.py:406BackgroundAudioPlayer.aclose()
收背景音 track 時呼叫 unpublish_track()。這是唯一會 unpublish 的地方,
用法本身沒問題(跟 upstream 一致),純粹是踩到 SDK 的 race。

TO BE

Pin 改成 livekit==1.1.13,帶進 upstream livekit/python-sdks#692 的修正
(issue livekit/python-sdks#6811.1.11 起已修)。修法是防護性查找 +
補上 track reference 清理:

elif which == "local_track_unpublished":
    sid = event.local_track_unpublished.publication_sid
    unpublished = self.local_participant._track_publications.get(sid)   # ← .get()
    if unpublished is not None:
        ...
        self.emit("local_track_unpublished", unpublished)
        if track is not None:
            unpublished._track = None
    else:
        logging.debug("local_track_unpublished for untracked publication sid %s", sid)

同時對齊 upstream livekit/agents main 的 pin(也是 livekit==1.1.13)。

相容性檢查(1.1.9 → 1.1.13)

我把兩版 wheel 抓下來逐項比對過:

檢查項 結果
EventTypes 事件移除 無(removed: none)
__all__ 移除的 export 只有 PacketTrailerFeature → 更名 FrameMetadataFeaturefork 與 app 都沒用到
LocalTrackPublication.packet_trailer_features frame_metadata_features沒有呼叫點
create_audio_track signature source 型別由 AudioSource 放寬成 Union[AudioSource, PlatformAudioSource],positional 呼叫不變 → 本 repo 3 個呼叫點(background_audio.py:530room_io/_output.py:67avatar/_runner.py:108)全相容
本 repo 依賴的 rtc private attr(_token / _server_url / _rpc_handlers / _info 1.1.13 全數存在

新增的是 PlatformAudio 系列 API(AudioDeviceInfo / PlatformAudioSource 等),
純新增,不影響既有路徑。

影響

這個 KeyError 本身是良性的 —— 唯一後果是那次 local_track_unpublished
事件沒 emit 出去,而本 repo 與 pathors app 都沒有任何地方監聽這個事件。
真正的成本是它污染 pathorsAI/pathors#1071 建立的 LiveKit error alert 訊號,
讓真正的錯誤更難被看見。

驗證

  • 兩版 wheel API surface diff(如上表),無 breaking change 命中本 repo
  • 主 repo re-lock 後跑一通 inbound + 一通 outbound,確認 teardown 不再噴 traceback(在 pathorsAI/pathors 的配套 PR 驗)

配套 PR(bump submodule pointer + uv.lock)在主 repo,會等這支 merge 後指過去。

## AS IS
- pin `livekit==1.1.9`,該版 `_on_room_event` 對 `local_track_unpublished`
  直接做 `track_publications[sid]` 無防護查找
- `unpublish_track()` 的 FFI response 與同一條 queue 上的
  `local_track_unpublished` RoomEvent 賽跑,response 先到就 KeyError
- 生產環境每通電話 teardown(BackgroundAudioPlayer.aclose())都可能噴
  ERROR + traceback

## TO BE
- pin `livekit==1.1.13`,含 upstream livekit/python-sdks#692 的修正
  (改為 `.get(sid)` 防護性查找 + 補上 `_track = None` 清理)
- 對齊 upstream livekit/agents main 的 pin
@YJack0000
YJack0000 requested a review from yui0303 July 24, 2026 11:58
@YJack0000

Copy link
Copy Markdown
Author

改走既有的 claude/agents-pathors-rebase-qh7tvv branch(已經是 upstream main + 我們 3 個客製 patch,livekit pin 自然是 1.1.13),不另外在這個 repo 開 minimal pin bump。agents repo 的變更交由 @yui0303 決定,主 repo 側的 submodule bump 走 pathorsAI/pathors#1274。

@YJack0000 YJack0000 closed this Jul 24, 2026
@YJack0000
YJack0000 deleted the fix/livekit-rtc-1.1.13-unpublish-keyerror branch July 24, 2026 12:07
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.

1 participant