jolly-dawn-15477
02/12/2026, 8:04 PMtall-airline-16756
02/12/2026, 8:04 PMIsFormatSampleRateAndChannelCountValid(format) means iOS rejected the audio format (sample rate or channel count) of a track — usually an unsupported or unexpected sample rate/channels combination.
• The “could not find local track subscription for subscribed event” warning is usually a race/ordering issue between publishing/subscribing and room state sync; it’s often non-fatal but worth addressing to avoid missed subscriptions.
CoreAudio assertion — what’s happening
• iOS CoreAudio validates that an audio buffer’s sample rate and number of channels are supported. If your published audio track (or a modified/processed version of it) has a nonstandard sample rate or channel count, CoreAudio throws that assertion.
• Common triggers:
◦ A track created or converted with an unsupported sample rate (e.g., 8 kHz or a mismatched rate) or an unexpected channel count (e.g., 2 channels when an API expects 1).
◦ Post-capture processing that changes sample rate or channels without proper audio conversion.
◦ A mismatch between the audio source’s configured rate and the device/AVAudioSession settings.
Immediate checks to perform
1. Confirm the capture format on the client:
◦ Ensure microphone capture/sample rate and channel count are set to common supported values (for example, sample_rate = 16000 or 48000, num_channels = 1).
1. Check any processing pipeline:
◦ If you resample, mix, or otherwise process audio (on device or server/agent), verify you’re performing a proper conversion (resampling and channel remapping) before passing audio to LiveKit or CoreAudio APIs.
1. Verify AVAudioSession settings (iOS):
◦ Make sure AVAudioSession category, mode, and preferred sample rate align with the track format you publish.
1. Review published track metadata:
◦ When you publish a track, log its sample rate and channel info. If the published track has unusual values, track where they come from.
1. Reproduce with device logs:
◦ Reproduce the issue on a device while capturing full device logs (Console) to see if format negotiation messages appear before the assertion.
Quick mitigations to try
• Force a supported format at capture: set the microphone / AudioSource to 16000 Hz / mono (1 channel) as a safe baseline.
• If you use an intermediate encoder/decoder, ensure it outputs a supported sample rate and channels.
• If you only see this with certain devices/OS versions, try forcing a consistent AVAudioSession preferredSampleRate and convert incoming audio if needed.
“Could not find local track subscription for subscribed event” — what it means
• This indicates the SDK received a subscribed event for a remote track but couldn’t match it with an expected local subscription object.
• Typical root causes:
◦ Race condition during signaling/SDP negotiation — the remote publishes a track and the SDK dispatches a subscribed event before local state is fully synced.
◦ Transient network/packet reordering causing out-of-order events.
◦ Edge cases in subscribe/unsubscribe flows when a participant quickly publishes/unpublishes or joins/leaves.
How to diagnose and mitigate
1. Correlate timing with the CoreAudio error:
◦ In your logs the publish happened, then the warnings and CoreAudio assertion shortly after; see whether specific participants/devices coincide with both issues.
1. Ensure stable join/publish sequencing:
◦ Wait until the local participant has fully joined/connected before publishing tracks, when feasible.
1. Add defensive handling in the client:
◦ When you get “could not find local track subscription” messages, retry subscription or gracefully ignore then resubscribe when room state updates arrive.
1. Increase logging around signaling events:
◦ Log join/participant-joined, track-published, subscribed, and remote-joined timestamps to identify ordering issues.
1. Network reliability tests:
◦ Check whether these warnings increase on flaky connections; higher rates of message reorder/loss make timing races more likely.
Combined troubleshooting approach
• Start by forcing a safe audio format (e.g., 16 kHz mono) on the offending client(s) and see if the CoreAudio assertion stops — this addresses the most severe issue first.
• While reproducing, capture detailed event logs (join, publish, subscribed, track events) and timestamps to see if the subscription warning is synchronous with publication.
• If forcing the format fixes the CoreAudio crash but you still see subscription warnings, focus on the timing/debugging steps for the subscribe race.
If you want, I can:
• Provide a small iOS checklist/snippet showing how to set AVAudioSession preferredSampleRate and force mono capture.
• Suggest client-side retry logic or a minimal debounce to ignore early subscribe events and wait for full room sync.
• Help interpret more logs: paste a short time-ordered sequence of the join/publish/subscribed messages and I’ll point out likely ordering issues.
Which would you prefer to try first — sample-rate forcing snippet (iOS) or subscription retry/debounce logic?
Sources: Resolving "InvalidState - failed to capture frame" errors in AudioSource | ... | client-sdk-unity | livekit/livekit_composite | DeepWikijolly-dawn-15477
02/13/2026, 2:39 PMtall-airline-16756
02/13/2026, 2:40 PMproactivity=True, Gemini realtime can decide not to produce output for inputs it thinks don’t require a reply. That matches your log: assistant message exists but text: "".
• If you need guaranteed acknowledgements, disable proactivity or change system instructions so the model always replies.
1. Short / ambiguous / fragmented utterances
• Filler words, interrupted phrases, or low-content utterances can make the model treat the input as non-actionable and return an empty reply.
• Even if the STT shows text, the semantic content may be insufficient for the assistant to produce a response.
1. Premature endpointing / VAD behavior
• The server-side VAD or turn detection may endpoint a user turn early (noise, partial speech), so the model sees an incomplete utterance and decides not to respond.
• This can be exacerbated by noisy audio, packet loss, or a user trailing off.
1. Model policy/behavior (not a bug)
• The model sometimes emits an empty assistant output depending on context and configuration — this is expected model behavior rather than an SDK error.
What to log/observe next (so you can pinpoint root cause)
• Timestamps for: user speech start, user speech final/transcript event, VAD endpoint event, model request send time, model response time.
• STT event contents and whether they were interim or final.
• Whether proactivity was true in the model config.
• Any VAD events from Silero (if used) or server-side endpointing signals.
• Audio length (seconds) and audio quality metrics for the turn.
Actionable fixes and mitigations
1. Disable proactivity (if you want a reply every time)
• Example: set proactivity: false on your RealtimeModel. This forces the model to produce a response instead of selectively staying silent.
1. Provide a fallback instruction / force acknowledgement
• Add an instruction or call generate_reply() with guidance like “Always acknowledge the user; if unclear ask a clarifying question.”
• Example pattern:
◦ On empty assistant output, call session.generate_reply({ instructions: "Acknowledge the user even if the request is vague." }) or re-run a short prompt that forces an acknowledgement.
1. Gate or debounce finalization using VAD / thresholds
• If turns are often cut off, use VAD thresholds or a short debounce (e.g., 200–500 ms confirm silence) before sending the final audio to the model so it receives a more complete utterance.
• Be mindful: server-side VAD for Gemini is used, so adjust local gating only to avoid sending premature endpoints.
1. Improve audio quality and endpointing reliability
• Reduce background noise, enable noise reduction if available, and ensure stable network so the server receives full audio.
• Log audio length — if most empty responses come from very short audio (< ~1s), you can treat those as likely low-content.
1. Instrument and retry: treat empty responses as a trigger
• If you detect an empty assistant reply programmatically, automatically:
◦ ask a clarifying question, or
◦ re-run the generation with explicit instructions, or
◦ request the user to repeat the last utterance.
Example flows
• Force replies:
◦ Set proactivity=false on model init.
◦ If an empty reply arrives, call generate_reply() with “Please acknowledge or ask a clarification.”
• Debounce endpointing:
a. Wait an extra 200–500ms after VAD says “speech ended” before sending final chunk to the model.
b. If additional audio arrives in that window, treat it as part of the same turn.
When to dig deeper / what to send me
• If you want help diagnosing this exact case, share:
◦ model config (is proactivity=true?), VAD settings, and whether you use Silero
◦ a time-ordered log showing VAD events, STT interim/final events, and model request/response times for that turn
◦ audio length for the user utterance
I can then point to whether endpointing or model config is the likely root cause and show code snippets to implement the fallback/debounce behavior.
Which would you like next — a snippet showing how to disable proactivity and force a fallback reply, or a small instrumentation snippet to log VAD + STT + model timings so we can detect the pattern precisely?
Sources: Google Gemini LLM plugin guide | LiveKit Documentation | Gemini Realtime Agent with Live Vision | LiveKit Documentation | Agent speech and audio | LiveKit Documentation | VAD and turn detection configuration guide | LiveKit | Turns overview | LiveKit Documentation