Include the device error code in connection failure logs#5525
Conversation
When a connection to a device fails, the error returned by tinytuya is
discarded and only "Failed to refresh device state for <name>." is
logged, so every cause looks the same in the log.
This is most confusing for error 914. tinytuya returns it for any
failure to negotiate a session, and its message ("Check device key or
version") only names two of the possible causes. A device that has
stopped accepting local connections and needs to be power cycled
reports the same 914, with a correct key and protocol version. That
case is a recurring source of reports (make-all#5347, make-all#5136, and jasonacox/
tinytuya#581), and the log currently gives no way to tell it apart
from a genuine misconfiguration.
Log the error code and the device's message alongside the existing
text, and for 914 spell out the causes it can stand for.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| # until it is power cycled, not just a misconfigured key or protocol version. | ||
| _ERROR_HINTS = { | ||
| "914": ( | ||
| " (an incorrect local key or protocol version, or a device that has " |
There was a problem hiding this comment.
Is this supposed to be a standalone message to replace the tinytuya one, or a snippet to append to the end?
I see it is in parentheses so probably the latter, and that seems to be how it is formatted. In that case you don't need to repeat the information that is already in the tinytuya message, and don't deemphasize it by putting it in parentheses.
I suggest " Alternatively the device may have stopped accepting local connections and needs to be power cycled."
There was a problem hiding this comment.
Append, yes. It's concatenated onto tinytuya's message, so I didn't want to fully replace it. You're right that the parens buried the important part. Your wording reads better than mine, thanks for taking it.
I pushed a small ruff format commit on top. Dropping the second string left the parens wrapped across two lines, so format --check was failing CI. Should be green now.
The single-line hint string no longer needs to be wrapped, which ruff format --check (run in CI) was flagging. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
These were only needed for the multi-line version to group the separate strings into a single statement
Problem
When a device connection fails,
_retry_on_failed_connectioncaptures the error tinytuya returned but then logs only the generic message:The error code is dropped. Enabling debug logging doesn't recover it either — the code is never formatted into any message, so the only way to see it today is to reproduce the call outside Home Assistant with tinytuya directly.
This matters most for error 914. tinytuya returns 914 for any failure to negotiate a session, but its message — "Check device key or version" — names only two of the causes. A device that has stopped accepting local connections and needs a power cycle returns the same 914 with a perfectly correct key and protocol version.
That case is common: #5347, #5136, #4862 and jasonacox/tinytuya#581 are all the same shape — the device works fine in the Tuya app, tinytuya says 914, and only a power cycle fixes it. Because the log says nothing, every one of those reports starts by re-checking the local key, which is not the problem.
I hit this on a Treatlife DS03. The stored key was byte-identical to the one in the cloud, and the device still returned 914 on every protocol version. The log gave no hint that "check your key" was a dead end.
Change
Keep the error code and the device's own message, and log them with the existing text. For 914, spell out the causes it can stand for:
Failures that aren't device errors (socket errors, timeouts) log exactly as before.
The existing carve-out that keeps 914 at debug level while auto-detecting the protocol version is untouched — 914 is expected there, and that path stays quiet.
Tests
Three tests added to
tests/test_device.py:test_refresh_error_reports_device_error_code— the code, the message and the 914 hint appear in the error log. Fails without this change.test_refresh_error_without_error_code_is_unchanged— a plain exception still logs the bare message, with no "Device reported error" suffix.test_refresh_error_914_stays_quiet_when_rotating_protocols— 914 during protocol auto-detection still does not log at error level.pytest tests/test_device.py→ 43 passed.ruff checkandruff format --checkclean.Note
This only makes the failure legible; it doesn't fix it. The underlying device-side fault belongs upstream in tinytuya, where 914 conflates causes that are distinguishable on the wire. I'm investigating that separately and will report it there.
🤖 Generated with Claude Code