Appearance
Maximum payload lengths
This page is the single reference for how large a single frame and a logical multi-fragment message may be. Related: Packet layout, Fragmentation, Text encoding.
SX1262 (and SX1261): maximum LoRa packet payload
For LoRa® with explicit header mode, Semtech SX1261 / SX1262 document SetPacketParams → LoRa PayloadLength (PacketParam4) with a range of 1 to 255 bytes. That value is the length of the payload written to the chip’s buffer for that packet — i.e. the maximum single LoRa PHY payload is 255 bytes for the modem payload field (CRC handling is separate in the modem; do not double-count against the 255 when following Semtech driver usage).
Reference: Semtech datasheet SX1261/SX1262, LoRa PacketParam4 — PayloadLength (see current revision of DS.SX1261-2 on semtech.com).
LowMesh implication: Treat 255 bytes as the hard ceiling for one over-the-air Mesh PDU (everything you pass as the LoRa packet payload: dynamic headers + prefix blocks + encrypted application tail), unless you use a different radio or implicit header with a smaller fixed size.
No payloadLen field
The mesh framing does not carry a single payloadLen byte. Implementations derive the application tail length from the modem rxSize (or TX builder cursor) minus the sum of:
- Base header size (16 or 20 bytes depending on
HAS_DST_ID), - optional Spatial Region block (5 bytes if
HAS_REGION), - optional Fragment block (2 bytes if
HAS_FRAGMENT), - optional Routing block (
1 + pathCount × hashSizebytes ifhopControlbit 7 / wirettlRaw & 0x80, withhashSize = ((verFlags >> 9) & 3) + 1).
[ \textbf{prefixBytes} = \textbf{base + region + frag + route} ] [ \textbf{appTailLen} = \textbf{rxPhyLen} - \textbf{prefixBytes} ] [ \textbf{cipherLen} = \textbf{appTailLen} - \textbf{micLen} ]
TX stacks MUST ensure the entire Mesh PDU ≤ 255 bytes. Floods MUST additionally respect hop/hash-size policies so relays do not grow frames past the PHY cap — see Routing.
Single over-the-air frame (one Mesh PDU)
channelHash | MIC inside application tail? |
|---|---|
0x0000 (default community) | Yes — AES-256-CCM-4 with defaultCommunityPsk32 |
| non-zero (named / DM) | Yes — 4-byte AES-256-CCM-4 MIC after ciphertext |
Normative: All channelHash values, including 0x0000, use AES-256-CCM-4. The default community domain uses the fixed ROM defaultCommunityPsk32 unless a product profile overrides it — encrypted/authenticated on-air, but not private against other LowMesh devices (globally shared key). There is no plaintext default-channel inner payload in the current specification.
Logical messages (fragmented)
Fragmentation is not limited by one frame’s application tail alone:
- Each fragment is still one Mesh PDU with its own fragment block when
HAS_FRAGMENTis set. - The reassembled blob (file, long text, voice) can be much larger.
Documented informal range (see Text encoding):
| Use | Typical logical size |
|---|---|
| Fragmented chat / file | 64 KiB – 1 MiB (policy; enforce RAM caps in firmware) |
Upper bound is implementation (RAM, flash, airtime).
USB / BLE hex API
The line-oriented hex API is not the same as RF:
- Long frames are split across multiple hex lines or use binary mode; see USB & BLE hex API.
- BLE ATT MTU (often 23–247) limits how many bytes fit in one GATT write unless you chunk — this affects transport, not on-air Mesh PDU layout.
Summary table
| Layer | Limit |
|---|---|
| SX1262 LoRa PHY payload | 255 bytes max (PayloadLength 1–255) |
| Mesh PDU | ≤ 255 bytes total (dynamic headers + tail) |
| Application tail | appTailLen = rxPhyLen − prefixBytes; cipherLen = appTailLen − micLen; on-air **`cipherLen |
| Reassembled multi-fragment message | 64 KiB–1 MiB typical policy; hard cap = implementation |