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

  1. Only start the audio pump after StartIntercom returns successfully
  2. Re-run the intercom/AV server setup before resuming audio sends
  3. Check whether serverConn was invalidated by an earlier handshake failure and restart the session
  4. 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

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


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)