Skip to content

AttributeError: 'bytes' object has no attribute 'encode' – double bytes conversion before _aes_encrypt() #3

Description

@hgsdfhjgs

Description

Playback via media_player.play_media (and TTS) fails immediately with:

AttributeError: 'bytes' object has no attribute 'encode'. Did you mean: 'decode'?

The error occurs regardless of the audio source — it happens with TTS (tts.speak) as well as with a local MP3 via media-source://. So it is not audio-related, it happens during the Baichuan talk handshake.

Environment

Home Assistant 2026.x (Python 3.14)
reolink_aio version bundled with current HA core
Integration installed via HACS from this repo
Camera Reolink, TrackMix & E1 Pro

Full traceback

File "/config/custom_components/reolink_talk/media_player.py", line 168, in async_play_media
    await self._play_bytes(media_bytes)
File "/config/custom_components/reolink_talk/media_player.py", line 288, in _play_bytes
    await talk_playback(bc, self._target.channel, adpcm_bytes, ability, block_align=full_block_size)
File "/config/custom_components/reolink_talk/talk.py", line 791, in talk_playback
    await send_talk_binary(bc, channel, payload, enc_type=enc_used)
File "/config/custom_components/reolink_talk/talk.py", line 609, in send_talk_binary
    enc_ext = bc._aes_encrypt(ensure_bytes(ext, name="extension XML"))
File "/usr/local/lib/python3.14/site-packages/reolink_aio/baichuan/baichuan.py", line 445, in _aes_encrypt
    return cipher.encrypt(body.encode("utf8"))
AttributeError: 'bytes' object has no attribute 'encode'

Root cause

talk.py line 609 passes the extension XML through ensure_bytes() before handing it to reolink_aio's _aes_encrypt():

enc_ext = bc._aes_encrypt(ensure_bytes(ext, name="extension XML"))

However, _aes_encrypt() in reolink_aio/baichuan/baichuan.py (line 445) expects a str and calls .encode("utf8") internally:

return cipher.encrypt(body.encode("utf8"))

So the value is converted to bytes twice. Since _aes_encrypt() lives in the official upstream library, it cannot be patched locally — the conversion has to be removed on this side.

Fix that works for me

Changing line 609 in talk.py to pass a str instead resolves the issue:

enc_ext = bc._aes_encrypt(ext.decode("utf-8") if isinstance(ext, bytes) else ext)

After a restart, both TTS and local MP3 playback work correctly.

Note

There may be other call sites of _aes_encrypt() with the same pattern that I haven't triggered yet — might be worth grepping for _aes_encrypt and ensure_bytes across the codebase.

Happy to test a patch. Thanks for building and maintaining this integration!

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions