{"record":{"id":"bdd03cd6a5960c60","repo":"AlexxIT/go2rtc","slug":"failed-to-decode-hex-w","errorCode":null,"errorMessage":"failed to decode hex: %w","messagePattern":"failed to decode hex: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/tuya/mqtt.go","lineNumber":183,"sourceCode":"\tc.closed = true\n}\n\n// WakeUp sends a wake-up signal to battery-powered cameras (LowPower mode).\n// The camera wakes up and starts responding immediately - we don't wait for dps[149].\n// Note: LowPower cameras sleep after ~3 minutes of inactivity.\nfunc (c *TuyaMqttClient) WakeUp(localKey string) error {\n\t// Calculate CRC32 of localKey as wake-up payload\n\tcrc := crc32.ChecksumIEEE([]byte(localKey))\n\n\t// Convert to hex string\n\thexStr := fmt.Sprintf(\"%08x\", crc)\n\n\t// Convert hex string to byte array (2 chars at a time)\n\tpayload := make([]byte, len(hexStr)/2)\n\tfor i := 0; i < len(hexStr); i += 2 {\n\t\tb, err := hex.DecodeString(hexStr[i : i+2])\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to decode hex: %w\", err)\n\t\t}\n\t\tpayload[i/2] = b[0]\n\t}\n\n\t// Publish to wake-up topic: m/w/{deviceId}\n\twakeUpTopic := fmt.Sprintf(\"m/w/%s\", c.deviceId)\n\ttoken := c.client.Publish(wakeUpTopic, 1, false, payload)\n\tif token.Wait() && token.Error() != nil {\n\t\treturn fmt.Errorf(\"failed to publish wake-up message: %w\", token.Error())\n\t}\n\n\t// Subscribe to lowPower topic to receive dps[149] status updates\n\t// (we don't wait for this signal - camera responds immediately)\n\tlowPowerTopic := fmt.Sprintf(\"smart/decrypt/in/%s\", c.deviceId)\n\tif token := c.client.Subscribe(lowPowerTopic, 1, c.onLowPowerMessage); token.Wait() && token.Error() != nil {\n\t\treturn fmt.Errorf(\"failed to subscribe to lowPower topic: %w\", token.Error())\n\t}\n","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/tuya/mqtt.go#L165-L201","documentation":"WakeUp builds a binary payload by decoding the hex string two characters at a time with hex.DecodeString; this error wraps any hex decoding failure. It means the hex string passed to WakeUp is malformed — odd length or containing non-hex characters. The message is never published in this case.","triggerScenarios":"Calling WakeUp with a deviceId-adjacent hex string argument that has an odd number of characters or contains characters outside [0-9a-fA-F]; hex.DecodeString fails on one of the 2-char slices.","commonSituations":"Happens when a device key or payload was copied with extra whitespace/quotes, when a base64 string is mistakenly passed where hex is expected, or when a truncated key (odd length) is loaded from config.","solutions":["Validate the hex string length is even before calling WakeUp","Validate all characters are valid hex (regexp ^[0-9a-fA-F]+$)","Check where the hex string comes from (config/env/DB) for truncation or encoding mistakes","If the source is base64, decode with base64.StdEncoding instead of hex"],"exampleFix":"// before\nerr := client.WakeUp(devKey)\n// after\nvar re = regexp.MustCompile(`^[0-9a-fA-F]+$`)\nif len(devKey)%2 != 0 || !re.MatchString(devKey) {\n    return fmt.Errorf(\"invalid hex key: %q\", devKey)\n}\nerr := client.WakeUp(devKey)","handlingStrategy":"validation","validationCode":"var hexRe = regexp.MustCompile(`^[0-9a-fA-F]+$`)\nfunc validHex(s string) bool { return len(s)%2 == 0 && hexRe.MatchString(s) }","typeGuard":"func isHexString(s string) bool {\n    if len(s) == 0 || len(s)%2 != 0 { return false }\n    _, err := hex.DecodeString(s)\n    return err == nil\n}","tryCatchPattern":"if !isHexString(key) { return fmt.Errorf(\"not a valid hex key: %q\", key) }\nif err := client.WakeUp(key); err != nil {\n    var hexErr *hex.InvalidByteError\n    if errors.As(err, &hexErr) { /* malformed input, do not retry */ }\n}","preventionTips":["Validate hex keys at config-load time, not at call time","Store keys with a fixed-length schema check","Never pass base64-encoded keys where hex is expected"],"tags":["go","hex","encoding","validation","tuya"],"backgroundTag":"invalid-argument-format","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}