AlexxIT/go2rtc · error

wrong message prefix

Error message

wrong message prefix

What it means

Roborock IoT Decrypt guard: the ciphertext is shorter than 32 bytes or does not start with the expected '1.0' protocol version prefix, so it is not a valid Roborock encrypted IPC message. Usually means desynced framing, wrong devKey, or a non-Roborock endpoint responding.

Solutions

  1. Verify the local devKey matches the device
  2. Check that the connection is talking to the Roborock IoT endpoint and framing is intact
  3. Reconnect to resynchronize the message stream
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at pkg/roborock/iot/crypto.go:20 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at pkg/roborock/iot/crypto.go:20

import (
	"crypto/aes"
	"crypto/md5"
	"encoding/binary"
	"errors"
	"hash/crc32"
)

// key - convert timestamp to key
func (c *Codec) key(timestamp uint32) []byte {
	const salt = "TXdfu$jyZ#TZHsg4"
	key := md5.Sum([]byte(encodeTimestamp(timestamp) + c.devKey + salt))
	return key[:]
}

func (c *Codec) Decrypt(cipherText []byte) ([]byte, error) {
	if len(cipherText) < 32 || string(cipherText[:3]) != "1.0" {
		return nil, errors.New("wrong message prefix")
	}

	i := len(cipherText) - 4
	if binary.BigEndian.Uint32(cipherText[i:]) != crc32.ChecksumIEEE(cipherText[:i]) {
		return nil, errors.New("wrong message checksum")
	}

	if proto := binary.BigEndian.Uint16(cipherText[15:]); proto != 102 {
		return nil, nil
	}

	timestamp := binary.BigEndian.Uint32(cipherText[11:])
	return decryptECB(cipherText[19:i], c.key(timestamp)), nil
}

func (c *Codec) Encrypt(plainText []byte, seq, random, timestamp uint32) []byte {
	const proto = 101

View on GitHub (pinned to c245815e75)