Gotchas
Use this page only for library-specific caveats.
Shared SLMP setup, profile, point-limit, and end-code symptoms live in the shared SLMP Troubleshooting & Codes page. For profile limits and device availability, use the shared SLMP Profile Parameters page.
Current library-specific caveats
| Area | Symptom | Guidance |
|---|---|---|
| IPv6 endpoint | connect() rejects an IPv6 literal or the supplied Arduino transport rejects a hostname. |
The library contract is IPv4-only. Supplied Arduino TCP/UDP transports require a numeric IPv4 literal. A custom transport may support hostnames only when it resolves and connects to IPv4 without IPv6 fallback. |
| Diagnostics | Bytes are received, but the response is rejected as an invalid SLMP frame. | Verify the PLC Binary data-code setting and inspect lastRequestFrame() / lastResponseFrame() with formatHexBytes(). |
| Buffer sizing | A request fails locally with BufferTooSmall. |
Size TX for the complete 3E/4E request frame and RX for the larger of the maximum success response or PLC error-information response. Caller output arrays are checked independently. Random-label reads must supply their maximum encoded response-data bound. The rejection occurs before frame/serial/state mutation or send. |
| Transaction timeout | A read returns Timeout and the client is disconnected. |
The one absolute TX-through-decode deadline expired. Reconnect explicitly before another operation; foreign responses and partial progress never extend the deadline. |
| Timeout configuration | setTimeoutMs() returns Busy, including when passed zero. |
Timeout configuration is idle-only and Busy admission precedes value validation. Wait until the request ends or configure a separate client; the active request keeps its original deadline. |
| PLC error correlation | A non-zero PLC end-code response becomes ProtocolError, or a write becomes OutcomeUnknown with cause ProtocolError. |
A structured error-information block did not match the active route, command, or subcommand. Reconnect because the transport generation is closed, inspect state before any state-changing retry, and use lastResponseFrame() for the complete rejected frame. |
| Unknown state-changing outcome | A write, remote-control, password, error-clear, or monitor-registration operation returns OutcomeUnknown. |
Some request bytes may have reached the PLC, but confirmation failed. Read lastOutcomeUnknownReason(), inspect the PLC/process state, and never resend automatically. |
| Local close | Closing an active read leaves Closed; closing after a state-changing request may have started leaves OutcomeUnknown with cause Closed. |
Treat close as transport-generation retirement. Reconnect explicitly and inspect state before considering another write. |
| Header selection | Names such as slmp::highlevel::readTyped or slmp::highlevel::Poller are undefined. |
Include slmp_high_level.h explicitly in any file that uses the high-level facade. |
| Shared client | A second operation returns Busy. |
One client owns one in-flight request and must not be called concurrently from multiple threads/tasks. Use independent transports and buffers for independent clients. |
| Bit-in-word update | A writeBitInWord or address-form writeTyped call with .bit succeeds but another writer's bit change is lost. |
Both entry points use the same explicit two-request read-modify-write and are not atomic. Use PLC-side logic or an application-level ownership/handshake scheme when coherence matters. |
| Device-range evidence aggregate | A live range catalog uses several reads on QCPU/LCPU/QnU/QnUDV profiles. | The complete probe decision plan is prevalidated and owns one synchronous client turn, but the evidence is non-atomic. Any non-PLC-NG intermediate error is returned and the caller's catalog remains unchanged. |