AlexxIT/go2rtc · error
av server not ready
Error message
av server not ready
What it means
AVSendAudioData requires an established DTLS server connection (serverConn). If none exists when audio is sent, the library returns this sentinel-style error instead of writing. It means audio was requested before the server-side AV session was ready.
Solutions
- Only start the audio pump after StartIntercom returns successfully
- Re-run the intercom/AV server setup before resuming audio sends
- Check whether serverConn was invalidated by an earlier handshake failure and restart the session
- Serialize session teardown and audio writing to avoid races
Example fix
// before
err := conn.WriteAudio(payload)
// after
if err := intercom.StartIntercom(ctx); err != nil {
return fmt.Errorf("cannot stream audio, session not established: %w", err)
}
err := conn.WriteAudio(payload) Defensive patterns
Strategy: try-catch
Validate before calling
if conn == nil || !conn.HasTwoWayStreaming() {
return fmt.Errorf("start intercom before writing audio")
} Type guard
func audioReady(c *dtls.DTLSConn) bool {
return c != nil && c.HasTwoWayStreaming()
} Try / catch
if err := conn.WriteAudio(frame); err != nil {
if err.Error() == "av server not ready" {
// (re)establish session, then resume audio pump
}
} Prevention
- Gate the audio writer loop on successful StartIntercom completion
- Stop the audio pump when the session tears down
- Re-establish the session before resuming audio
- Avoid racing teardown against audio writes
When it happens
Trigger: Calling WriteAudio -> AVSendAudioData before StartIntercom/AVServStart has completed and assigned c.serverConn, or after the session failed and serverConn was never set / was torn down.
Common situations: Application starts streaming audio before the intercom handshake finishes; a prior handshake error left the session dead while the audio pump keeps running; race between session teardown and the audio writer loop.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- nest: tried to stop rtsp stream without a project or device…
- wyze: failed to enable intercom
- pcm: unsupported audio format
- start from CONN state
- waw: unsupported codec
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/f0f1aa21bf9865f5.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/tutk/dtls/conn_dtls.go:332
func (c *DTLSConn) AVRecvFrameData() (*tutk.Packet, error) {
select {
case pkt, ok := <-c.frames.Recv():
if !ok {
return nil, c.Error()
}
return pkt, nil
case <-c.ctx.Done():
return nil, c.Error()
}
}
func (c *DTLSConn) AVSendAudioData(codec byte, payload []byte, timestampUS uint32, sampleRate uint32, channels uint8) error {
c.mu.Lock()
conn := c.serverConn
if conn == nil {
c.mu.Unlock()
return fmt.Errorf("av server not ready")
}
frame := c.msgAudioFrame(payload, timestampUS, codec, sampleRate, channels)
c.mu.Unlock()
n, err := conn.Write(frame)
if c.verbose {
if err != nil {
fmt.Printf("[SERVER TX] DTLS Write ERROR: %v\n", err)
} else {
fmt.Printf("[SERVER TX] len=%d, data:\n%s", n, hexDump(frame))
}
}
return err
}
func (c *DTLSConn) Write(data []byte) error {View on GitHub (pinned to c245815e75)