# Multi-level error retrieval and state-decision audit This report is based on static inspection of the bundled `source_reference/dobot_core/dobot_tcp.py` and `dobot_error.py`. It is not a hardware or network test. ## Call paths | Public API (via `DobotCtrl`) | `DobotTcp` | `DobotErrorManager` | Result | |---|---|---|---| | `get_error()` | `get_error()` | `get_error()` → `_get_error_records()` | Alarm ID list from `GetErrorID()` | | `get_error_code()` | `get_error_code()` | `get_error_code()` → `_get_error_records()` | First ID, or `0` if empty | | `get_error_count()` | `get_error_count()` | `get_error_count()` → `_get_error_records()` | Record count | | `check_error()` | `check_error()` | `get_error_count()` → `_get_error_records()` | `True` when count is zero | | `get_error_info(index)` | Same name | Same name → `_get_error_records()` → `_error_record_info()` | `None` for out-of-range index | | `get_current_error_info()` | Same name | Same name → `_get_error_records()` → `_error_record_info()` | Enriched alarm records | | `error_description` | Same property | Same property → `get_current_error_info()` | Empty string when no records | ## Where failures can become normal-looking values 1. `_get_error_records()` returns `[]` if the Dashboard object is `None`. 2. A nonzero or unparsable leading `GetErrorID()` return code is logged and converted to `[]`. 3. `_parse_error_groups()` returns `[]` for empty or malformed replies, invalid JSON, or non-list payloads. 4. Consequently, `get_error() == []`, `get_error_count() == 0`, `get_error_code() == 0`, and `check_error() is True` **do not uniquely establish that no alarm exists**. 5. If `dashboard.GetErrorID()` raises an exception, `_get_error_records()` has no handler around that call, so the exception may propagate. **Not every communication failure becomes an empty list.** ## Feedback-dependent motion error detection `motion_error_active()` catches `RuntimeError` from `_state_getter("ErrorStatus", timeout=0.1)` and substitutes `error_status=False`. With `query_error_id=False`, it does not query `GetErrorID()` unless Feedback indicates an error. With `query_error_id=True` or `ErrorStatus=True`, it queries `_get_error_records()`. `wait_motion_start_or_error()` monitors for 0.25 seconds by default, then performs a final check with `query_error_id=True`. This is a **limited post-acceptance check**, not verification of the entire motion. ## Operational implications - Do not infer communication health solely from `check_error()`. - Some error-retrieval failures cannot be distinguished from no-alarm responses through the current public return values. - External Dashboard exceptions depend on its implementation and are not guaranteed by this report. - This documents observed source behavior; it does not modify the implementation.