Error Handling: Our Safety Seatbelts

USMP operates on a very simple, security-first philosophy: **fail fast**.

USMP operates on a very simple, security-first philosophy: fail fast.

In some network protocols, if something goes wrong, the systems will try to negotiate, recover, or patch things up on the fly. In a security protocol, this is extremely dangerous. If there is a crack in a secure tunnel, we don't try to repair it while it's active. Instead, we immediately shred the session keys, close the connection, and build a brand-new tunnel from scratch.

Think of our error handling rules as safety seatbelts: if they detect any abnormal movement, they lock down instantly to protect your device and your data.

Note:

Reserved Status of PKT_ERROR The PKT_ERROR packet type (0xFF) and associated binary error codes are currently reserved in the protocol specification for future diagnostic telemetry. In the current reference implementation, both client and server immediately close the underlying transport connection without transmitting error frames. This prevents information leakage and timing attacks that could help an attacker map our service.

The PKT_ERROR Frame (0xFF) [Reserved]

When supported in future versions, if one side detects a protocol violation or cryptographic failure, it will attempt to tell the other side why it is disconnecting by sending a PKT_ERROR packet before closing the socket.

Payload Layout (3 bytes)

  • Byte 0 (1 byte): code — The error code integer.
  • Bytes 1..2 (2 bytes): detail — Optional supplementary details (u16 little-endian, such as the sequence number that caused a mismatch).

Standardized Error Codes (Reserved)

CodeNameWhat it means
0x01ERR_VERSION"You are speaking a protocol version I don't support."
0x02ERR_AUTH"The Pre-Shared Key (PSK) signature we exchanged didn't match."
0x03ERR_SEQ"A packet arrived out of order! Possible replay attack."
0x04ERR_CRYPTO"Decryption failed or the AES-GCM seal was tampered with."
0x05ERR_BAD_FRAME"The binary packet structure is invalid or too large."
0x06ERR_TIMEOUT"I waited too long for a handshake or keepalive reply."
0x07ERR_INTERNAL"An unexpected internal memory or crypto engine error occurred."

Safety Rules: How We Handle Violations

Here is exactly how the client and server react to various protocol violations:

ScenarioState Machine ActionRationale
Bad Magic BytesDiscard frame. Close connection instantly without sending PKT_ERROR.If a client sends bad magic bytes, it's either a random port scanner or a corrupted stream. Sending an error frame back could help an attacker map our service.
CRC Check MismatchDiscard frame. Close connection instantly without sending PKT_ERROR.Protects against line noise or packet tampering.
Wrong Protocol VersionDiscard frame. Close connection instantly without sending PKT_ERROR.Protects against version mismatch or scan attempts.
HMAC Signatures MismatchDiscard frame. Close connection instantly without sending PKT_ERROR.Indicates incorrect PSK or a brute-force authentication attempt.
Sequence Number MismatchDiscard frame. Close connection instantly without sending PKT_ERROR.Protects against replayed messages.
AES-GCM Decryption FailsDiscard frame. Close connection instantly without sending PKT_ERROR.Indicates key mismatch, corrupted data, or active tampering.
Timeout (No keepalives)Close connection instantly without sending PKT_ERROR.Clean up dead connections to free device resources.
Control Packet during FragmentationDiscard frame. Close connection instantly without sending PKT_ERROR.Interleaving standard packets while reassembling a fragmented payload is a protocol violation.
Max Fragments ExceededDiscard frame. Close connection instantly without sending PKT_ERROR.Plaintext payloads are capped at 452 bytes per frame, up to a maximum of 4 frames.

Developer Implementation

C Client Library (ESP-IDF & Arduino)

On the microcontroller, USMP logs the error description and tears down the local session context:

if (pkt.seq != ctx->rx_seq) {
    USMP_LOGE(TAG, "Sequence mismatch detected!");
    
    // Invalidate the session locally; transport is closed by usmp_recv returning error
    ctx->established = false;
    return -1;
}

Python SDK Exceptions

The Python SDK maps these binary error codes directly into standard Python exceptions. This makes it incredibly easy to write error-handling logic:

from usmp import USMPSession
from usmp.errors import ConnectionClosedError, CryptoError

async def handle_telemetry(session: USMPSession):
    try:
        while True:
            data = await session.recv()
            print(f"Received data: {data}")
    except ConnectionClosedError:
        print(f"Device {session.device_id} disconnected cleanly.")
    except CryptoError:
        # This will fire if someone tries to send data with a bad PSK or session key!
        print(f"Decryption failed for device {session.device_id}! Key mismatch or tampering.")
    except Exception as e:
        print(f"Unexpected error: {e}")

Here are the exception classes you can catch:

  • USMPError — Base exception for all USMP errors.
  • FrameError — Malformed binary structure.
  • CRCError — CRC check failed.
  • MagicError — Magic bytes (0xABCD) mismatch.
  • VersionError — Unsupported version.
  • HandshakeError — Key negotiation failed.
  • AuthError — PSK verification failed.
  • CryptoError — Decryption or GCM authentication tag failed.
  • SequenceError — Replay protection triggered (sequence number mismatch).
  • TimeoutError — Keepalive watchdog timer expired.