AlexxIT/go2rtc · error

speaker failed with resCode

Error message

speaker failed with resCode: %d

What it means

onMqttSpeaker parses the incoming MQTT message for a resCode field; if resCode is non-zero it completes the speaker waiter with this error, failing the pending SendSpeaker call. It means the camera explicitly rejected the speaker command with the given response code. This error is only surfaced through SendSpeaker's 'speaker wait failed' wrapper.

Solutions

  1. Log/resCode-map the numeric code to a meaningful cause (busy, unsupported, busy-decoding)
  2. Retry after the current operation completes or after waking the device
  3. Adjust speaker request parameters (resolution, sample rate, HEVC flag) to values the device supports
  4. Serialize speaker commands so overlapping calls don't get rejected

Example fix

// before
err := client.SendSpeaker(...)
if err != nil { return err }
// after
err := client.SendSpeaker(...)
if err != nil {
    var resCode int
    if _, ferr := fmt.Sscanf(err.Error(), "speaker failed with resCode: %d", &resCode); ferr == nil {
        return fmt.Errorf("device rejected speaker cmd (resCode=%d)", resCode)
    }
    return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

// validate speaker params against device capability table before sending
if !supportedResolution(res) { return fmt.Errorf("unsupported resolution %s", res) }

Try / catch

err := client.SendSpeaker(...)
if err != nil {
    var rc int
    if n, _ := fmt.Sscanf(err.Error(), "speaker failed with resCode: %d", &rc); n == 1 {
        return mapResCode(rc)
    }
    return err
}

Prevention

When it happens

Trigger: Any SendSpeaker call where the device's MQTT reply contains resCode != 0 (e.g. busy, decode failure, unsupported request). The JSON parse must succeed but the code is non-zero.

Common situations: Sending a second speaker command while one is active, sending during low-power state before the camera is fully awake, or a firmware that rejects certain resolutions/audio formats.

Related errors


AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07). Data as JSON: /api/errors/59d63ea8eea17383. Report an issue: GitHub.

Appendix: source

Thrown at pkg/tuya/mqtt.go:366

	candidateFrame.Candidate = strings.TrimPrefix(candidateFrame.Candidate, "a=")
	candidateFrame.Candidate = strings.TrimSuffix(candidateFrame.Candidate, "\r\n")

	c.onCandidate(candidateFrame)
}

func (c *TuyaMqttClient) onMqttDisconnect() {
	c.closed = true
	c.onDisconnect()
}

func (c *TuyaMqttClient) onMqttSpeaker(msg *MqttMessage) {
	var speakerResponse struct {
		ResCode int `json:"resCode"`
	}

	if err := json.Unmarshal(msg.Data.Message, &speakerResponse); err == nil {
		if speakerResponse.ResCode != 0 {
			c.speakerWaiter.Done(fmt.Errorf("speaker failed with resCode: %d", speakerResponse.ResCode))
			return
		}
	}

	c.speakerWaiter.Done(nil)
}

func (c *TuyaMqttClient) onAnswer(answer AnswerFrame) {
	if c.handleAnswer != nil {
		c.handleAnswer(answer)
	}
}

func (c *TuyaMqttClient) onCandidate(candidate CandidateFrame) {
	if c.handleCandidate != nil {
		c.handleCandidate(candidate)
	}
}

View on GitHub (pinned to c245815e75)