From 9c4851877174ec78ccc185ef1c1a2aa8a58b8fdd Mon Sep 17 00:00:00 2001 From: MarekWo Date: Tue, 9 Jun 2026 12:47:44 +0200 Subject: [PATCH] fix(channels): surface meshcore lib's error_code/code_string on resend failure The lib's reader.py wraps device ERROR frames as {error_code, code_string}, not {reason, error}. The previous extraction collapsed every device error to "unknown error", hiding the actual ERR_CODE_* the firmware sent back. Check code_string/reason/error in order, then fall back to a raw error_code, then "unknown error". Co-Authored-By: Claude Opus 4.7 --- app/device_manager.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/device_manager.py b/app/device_manager.py index 9784136..4e35c02 100644 --- a/app/device_manager.py +++ b/app/device_manager.py @@ -1772,9 +1772,16 @@ class DeviceManager: if event is None: return {'success': False, 'error': 'No response from device'} if event.type == EventType.ERROR: - err = getattr(event, 'payload', {}).get('reason') or \ - getattr(event, 'payload', {}).get('error') or 'unknown error' - logger.warning(f"Resend msg #{msg_id} failed: {err}") + payload = getattr(event, 'payload', {}) or {} + # meshcore lib's reader.py wraps device ERROR frames as + # {error_code: int, code_string: str}; commands.py wraps + # client-side failures as {reason: str} or {error: str}. + err = payload.get('code_string') or payload.get('reason') or payload.get('error') + if not err and payload.get('error_code') is not None: + err = f"error_code={payload['error_code']}" + if not err: + err = 'unknown error' + logger.warning(f"Resend msg #{msg_id} failed: payload={payload}") return {'success': False, 'error': f'Device rejected resend: {err}'} logger.info(f"Resent channel msg #{msg_id} via CMD_SEND_RAW_PACKET ({len(raw_packet)} bytes)") return {'success': True, 'message': 'Resent', 'id': msg_id, 'bytes': len(raw_packet)}