Symptom

A running Krill server logged a tight loop of errors while a Compose app (or any peer) was broadcasting its discovery beacon:

1
2
3
4
5
ERROR [ServerBeaconWireHandler] Error handling beacon from NodeWire(... host=box, port=0, platform=DESKTOP, ...)
java.lang.Exception: Node not found: d51ed48d-1e5a-406c-a115-3da8e17b802a
    at krill.zone.server.ServerNodeManager.readNodeState(...)
    at krill.zone.server.io.beacon.ServerBeaconSender.sendSignal(...)
    at krill.zone.server.io.beacon.ServerBeaconWireHandler$handleIncomingWire$1.invokeSuspend(...)

The id in the error (d51ed48d…) is the server’s own install id — not the beacon sender’s (8e561032…). The server never replied with its own beacon, so peers could not discover it; and because the reply ran before the server-to-server connect, that connect never executed either.

Root cause

ServerBeaconSender.sendSignal() resolved the local identity with ServerIdentity.getSelfWithInfo() (which falls back to a freshly built, port-resolved default when the self-node is not persisted) but then also re-read its own node out of the database via nodeManager.readNodeState(installId()) just to pull the port back off it. readNodeState throws Node not found when the node is absent. Any window where the server’s own KrillApp.Server node was not yet persisted — e.g. a beacon arriving before ServerNodeManager.init() saved it — made every beacon reply throw. ServerBeaconWireHandler.handleIncomingWire calls sendSignal() before serverConnector.connectWire(wire), so the throw also blocked storing server peers, not just app discovery.

The persisted node read was both redundant and worse than the value already in hand: getSelfWithInfo() returns a ServerMetaData whose port is already resolved to DEFAULT_PORT (8442) when the stored port is 0, whereas the raw persisted node could carry port 0.

Fix

Prevention