On this page
If you’ve been running MeshCore for a while, you’ve probably seen path.hash.mode in the CLI and wondered what it actually does. Maybe you noticed it show up in the v1.14.0 changelog as “multibyte path hash support” and moved on. Or maybe you’ve looked at a trace or a mesh map, seen two repeaters with the same ID, and had no way to tell which one carried your message. That problem is baked into the math.
This is the part of MeshCore most people skip over because it sounds abstract. It’s not. Path hashes are how your packets find their way across the mesh, and the size of those hashes decides whether you can still tell your repeaters apart once your mesh grows past a few dozen of them.
We’ve been running MeshCore across our own network and watching the multibyte rollout play out in community meshes. Here’s how it works, when it matters, and how to know when your mesh has outgrown the default. If you’re brand new to MeshCore, start with the getting started guide first. This post assumes you’re already running nodes.
What Path Hashes Actually Do
Every time a packet floods through the mesh, it picks up breadcrumbs. Each repeater that forwards the packet appends a short identifier (its path hash) to the packet’s path field before rebroadcasting. By the time the packet reaches its destination, the path field contains a complete trail of every repeater it touched along the way.
That trail is the whole point. The destination sends the path back to the original sender, and from then on neither side needs to flood the network to reach the other. The path field tells each of them exactly which repeaters to use, in order.
This is what makes MeshCore’s routing fundamentally different from flood-only systems. The first direct message to a contact floods. Every direct message after that follows the learned path, which is stored in the sender’s contact, so only the repeaters on that path retransmit it. (Channel messages always flood.) The path hash is what makes that direct routing possible.
So What Is the Hash
Each repeater’s path hash is the first N bytes of its public key. Not a hash of the path itself, and not really a hash at all: it’s a slice of the repeater’s identity. A truncated fingerprint that fits inside the packet without burning through your entire payload budget.
The question is how many bytes you use for that fingerprint. That’s what path.hash.mode controls.
- 1-byte mode (
path.hash.mode 0). Each repeater is identified by a single byte, the first byte of its public key. That gives you 254 usable IDs (0x00 and 0xFF are reserved). - 2-byte mode (
path.hash.mode 1). Two bytes per repeater. 65,536 possible IDs. - 3-byte mode (
path.hash.mode 2). Three bytes per repeater. Over 16 million possible IDs.
The path field in a MeshCore packet caps out at 64 bytes. Since each hop takes up N bytes of that space, the hash size directly controls how many hops a packet can traverse. (MeshCore’s docs give 64 hops for 1-byte mode, the size of the path field. The hop counter in the packet is 6 bits, so it actually tops out at 63.)
| Mode | Bytes per hop | Max hops | Unique IDs |
|---|---|---|---|
| 1-byte | 1 | 63 | 254 |
| 2-byte | 2 | 32 | 65,536 |
| 3-byte | 3 | 21 | 16,777,216 |
That’s the tradeoff. More bytes per hop means better identification, but fewer total hops before you run out of path space.
Why 1-Byte Mode Breaks at Scale
With 254 usable IDs, collisions aren’t just possible. They’re mathematically inevitable once your mesh grows past a certain size.
It’s the birthday problem. With 20 repeaters on random keys, the odds that at least two share the same first byte are already about 54%. At 40 repeaters it’s about 96%. Past 254 repeaters a duplicate is guaranteed, because there are no IDs left.
What does a collision actually break? Less than you might think, and MeshCore’s own FAQ is clear that flood and direct messages still reach their destinations. The real costs are these:
- You can’t tell the repeaters apart. A trace, a path display or a mapping tool sees
3Aand has no way to know which of the two3Arepeaters carried the packet. That’s the main reason the community pushed for bigger hashes. - Extra airtime on direct messages. A repeater forwards a direct packet when the next entry in the path matches the start of its own public key. If two repeaters with the same first byte both hear that packet, both forward it.
- Loop detection can misfire. The
loop.detectsetting drops flood packets where a repeater’s own ID already appears in the path too many times. On 1-byte paths, a same-ID repeater earlier in the path counts the same as a loop. Since 1.18 the default isminimal, which only drops a 1-byte packet once the repeater’s ID appears 4 times; the strictermoderateandstrictsettings are more likely to misfire.
The 2026 community discussion that led to multibyte support (#1613) shows how fast this adds up. One Irish operator reported 240+ repeaters seen on their regional mesh in a single day, close to the whole 1-byte ID space. Another commenter laid out the geometry: a repeater with 50 km range covers roughly 7,800 km². With only 256 identifiers spread over that area, each ID covers about 30 km², a circle with a 3 km radius. In any populated area, that’s not enough separation.
Before multibyte support existed, the workaround was manual coordination. Ottawa’s mesh keeps a public registry of all 256 IDs and reserves the C0 to CF block for links between cities. Operators generate keys with a first byte of their choosing (MeshCore’s FAQ points to a key generator for exactly this) and load them with set prv.key. It works, but only because people are paying attention. It was never going to scale.
How the Packet Encodes It
The path information lives in a single path_length byte, bit-packed:
- Bits 0 to 5. The hop count (0 to 63).
- Bits 6 to 7. The hash size, encoded as
(hash_size - 1).
So 0b00 in the upper bits means 1-byte hashes, 0b01 means 2-byte, 0b10 means 3-byte.
A few examples:
0x05= 5 hops, 1-byte hashes = 5 bytes of path data0x45= 5 hops, 2-byte hashes = 10 bytes of path data0x8A= 10 hops, 3-byte hashes = 30 bytes of path data
This encoding means the receiver always knows how to parse the path. It reads the hash size from the upper bits and the hop count from the lower bits. No ambiguity. No negotiation.
Signs Your Mesh Has Outgrown 1-Byte Mode
You won’t get an error message. Collisions mostly show up as confusion in the tools you use to understand the mesh. Here’s what to watch for.
The same ID shows up for two different repeaters. If a node list or mapping tool shows two repeaters whose public keys start with the same byte, every 1-byte path through either of them is ambiguous.
Duplicate repeats of direct messages. When two same-ID repeaters are in range of each other, both can forward a direct message meant for only one of them. One operator in #1613 reported seeing exactly this as duplicate repeats in trace views.
Growing repeater count. This is the simplest signal. Once your regional mesh has 30 or so repeaters, the odds of at least one shared first byte are above 80%. At 40 they’re about 96%. You don’t need to wait for symptoms. The math tells you it’s time.
Network mapping tools show ambiguous routes. Tools like the LetsMesh Analyzer and MeshMapper rely on path hash data to trace routes. With 1-byte collisions, these tools can’t reliably distinguish between two same-prefix repeaters. If your maps look wrong, this might be why.
Your community is coordinating first-byte prefixes by hand. If operators are picking keys to avoid collisions manually (the kind of thing covered in our repeater setup guide), that’s the clearest sign the system needs a bigger address space. Multibyte mode replaces the spreadsheet with math.
How to Switch
Check your firmware
Multibyte path hash support requires firmware v1.14.0 or later on all repeaters in the path. This is the hard constraint. Repeaters running older firmware will silently drop 2-byte and 3-byte packets. No error, no NACK, they just disappear.
Before switching your companion device to a larger hash size, confirm that the repeaters you depend on are updated. If even one critical repeater in your path is on pre-v1.14 firmware, your messages won’t make it through.
Repeaters on v1.14.0+ will forward all three hash sizes regardless of their own path.hash.mode setting. The mode only controls what size the repeater uses in its own adverts. This means you can upgrade repeaters progressively without worrying about intermediate states.
Set it on your repeater
Connect over USB serial, or log in to the repeater from the app and open its command line (see the full CLI reference for setup), and run:
set path.hash.mode 1 # 2-byte hashesOr for 3-byte:
set path.hash.mode 2 # 3-byte hashesCheck the current setting with:
get path.hash.modeAfter changing the mode, send a new advert so the network learns your updated hash:
advertThe MeshCore app (1.49.0 and newer) can also set a repeater’s path hash size from the network settings screen in remote management. Don’t worry about the shorter hop budget for adverts: on 1.18 firmware, repeaters only forward adverts 8 hops by default (flood.max.advert).
Set it on your companion
The repeater setting doesn’t touch your messages. The path hash size of a message is chosen by whoever sends it first, which is usually your companion. In the MeshCore app, set Default Path Hash Size in Settings (companion firmware 1.14.0 or newer). From app 1.41.0 to 1.48.0 this lived under Experimental Settings; 1.49.0 moved it to the main settings screen. Switching radio presets also applies that preset’s path hash size, so check it after a preset change. The app shows path hash info on contact detail screens so you can see what size each contact is using.
The transition period
During migration, expect a mixed network. Some repeaters will advertise 1-byte hashes, some 2-byte. This is fine. v1.14.0+ repeaters forward all sizes. The risk is only with pre-v1.14 hardware that can’t handle the larger packets.
The practical migration path:
- Update all repeaters to v1.14.0+ firmware first
- Switch repeaters to
path.hash.mode 1(2-byte) as you update them - Once the critical mass of repeaters is on v1.14.0+, switch companion devices
- Monitor for any paths that break. Those point to repeaters that still need updating.
Which Mode Should You Choose
Stick with 1-byte if your mesh is small (under 30 repeaters in range), you depend on very long hop chains (40+ hops for backhaul), or your region hasn’t finished upgrading repeaters to v1.14.0+. There’s no reason to rush if collisions aren’t a problem yet.
Go with 2-byte for most networks. You go from 254 IDs to 65,536 while dropping max hops from 63 to 32. Even 100 repeaters on random keys have only about a 7% chance of any shared 2-byte ID. Most regional paths are far shorter than 32 hops, but long interlinked meshes can exceed it: in #1613, one operator reported messages of more than 40 hops across Germany, the Netherlands, Belgium and the UK, and another said Australian links were already in the low 20s. Check your own longest paths first.
Consider 3-byte only for very large-scale deployments with hundreds or thousands of repeaters, where even 65k IDs start to collide (at 300 repeaters, the odds of a shared 2-byte ID are about 50%). The 21-hop limit is a real constraint, so make sure your network topology supports it before going there.
For NodakMesh and most community meshes in North America, 2-byte mode is the move. Our repeater infrastructure is on v1.14.0+, our hop counts are well under 32, and the collision headroom lets us grow without worrying about ID coordination.
The Bigger Picture
Path hashing is one of those details that doesn’t matter at all until it suddenly matters a lot. A mesh with five repeaters and 1-byte hashes works perfectly. A mesh with 80 repeaters and 1-byte hashes almost certainly has duplicate IDs, and every trace through them is a guess.
The introduction of multibyte path hashes in v1.14.0 was one of the most important scaling changes MeshCore has made. It doesn’t add new features. It removes a ceiling. For any community mesh that’s serious about growing, removing ceilings early is always cheaper than dealing with the problems they create later.
If you haven’t checked your path.hash.mode yet, now’s a good time. Run get path.hash.mode on your repeaters. If they’re on 0 and your mesh is growing, consider switching to 1. The change takes one command, and the ambiguity of not switching gets worse with every repeater you add.
For more on how MeshCore routing works under the hood, see our MeshCore explained guide. If you’re building new repeater infrastructure, the solar repeater build guide covers hardware, power, and deployment.
Comments
Related Posts

How MeshCore Works: Companions, Repeaters and Room Servers
A plain-English guide to MeshCore: what companions, repeaters and room servers do, how messages find a path, which frequency to use, and common fixes.

EasySkyMesh: Power-Efficient MeshCore Firmware
EasySkyMesh publishes MeshCore firmware tuned for low idle current: 8-10 mA on Heltec V3 and RAK4631 repeaters. Why that matters for solar nodes.
MeshCore vs Meshtastic: What Network Are You Building?
MeshCore relays only through repeaters and learns paths for DMs. Meshtastic lets every node relay. Pick by what you're building, not which protocol wins.