slackhq/nebula · warning

ErrAlreadySeen

ErrAlreadySeen

Error message

already seen

What it means

ErrAlreadySeen indicates a packet failed the replay window check: its message counter was already processed by this connection, so decryption is refused to prevent replay attacks. Declared in handshake_manager.go alongside the hostmap errors, it is returned by ConnectionState Decrypt/VerifyRelay when the replay filter rejects the counter.

Source

Thrown at handshake_manager.go:415

		// Add any calculated remotes, and trigger early handshake if one found
		doTrigger = hm.lightHouse.addCalculatedRemotes(vpnAddr)
	}

	if doTrigger {
		select {
		case hm.trigger <- vpnAddr:
		default:
		}
	}

	hm.Unlock()
	hm.lightHouse.QueryServer(vpnAddr)
	return hostinfo
}

var (
	ErrExistingHostInfo    = errors.New("existing hostinfo")
	ErrAlreadySeen         = errors.New("already seen")
	ErrLocalIndexCollision = errors.New("local index collision")
)

// CheckAndComplete checks for any conflicts in the main and pending hostmap
// before adding hostinfo to main. If err is nil, it was added. Otherwise err will be:
//
// ErrAlreadySeen if we already have an entry in the hostmap that has seen the
// exact same handshake packet
//
// ErrExistingHostInfo if we already have an entry in the hostmap for this
// VpnIp and the new handshake was older than the one we currently have
//
// ErrLocalIndexCollision if we already have an entry in the main or pending
// hostmap for the hostinfo.localIndexId.
func (hm *HandshakeManager) CheckAndComplete(hostinfo *HostInfo, handshakePacket uint8, f *Interface) (*HostInfo, error) {
	hm.mainHostMap.Lock()
	defer hm.mainHostMap.Unlock()
	hm.Lock()

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Treat isolated occurrences as benign network duplication and drop the packet
  2. If frequent, investigate path duplication (bonded links, redundant routing, virtual NICs) delivering every packet twice
  3. Ensure counters are not reset out-of-band (e.g. reloading an old hostinfo snapshot) which would make new traffic look replayed
Defensive patterns

Strategy: try-catch

Try / catch

out, err := cs.Decrypt(b, out)
if errors.Is(err, ErrAlreadySeen) {
    // replayed or duplicate packet: drop silently
    return
}

Prevention

When it happens

Trigger: Calling Decrypt or VerifyRelay on connection_state.go:104/116 where the NaCl/decrypt verification reports the message counter was already seen (result == false under cs.decryptLock).

Common situations: Duplicate UDP packets delivered by the network; packet replay (possibly malicious); out-of-order retransmits at the tunnel layer; restoring old packet captures onto a live connection.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/38c3d3de6501c540. Report an issue: GitHub.