OpenNHP/opennhp · error

relay: server invalid publicKeyBase64

Error message

relay: server %q invalid publicKeyBase64: %w

What it means

Raised in RelayServer.buildServer while converting a configured [[Servers]] entry into runtime state: decoding that server's PubKeyBase64 with standard base64 failed. The peer public key copied into the relay config for this upstream NHP server is malformed or was pasted in the wrong encoding.

Solutions

  1. Re-copy the server's public key from its config or keygen output into the relay config
  2. Remove surrounding whitespace/newlines introduced during copy-paste
  3. Confirm standard (not URL-safe) base64 is used
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at endpoints/relay/relay.go:257 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07). Data as JSON: /api/errors/b8e8f06354d80abf. Report an issue: GitHub.

Appendix: source

Thrown at endpoints/relay/relay.go:257

	log.Info("[Relay] initialized, relay pubkey=%s, %d server(s)",
		device.PublicKeyBase64(), len(rs.servers))
	for _, cr := range rs.servers {
		log.Info("[Relay]   server id=%s name=%q lb=%s instances=%d",
			cr.id, cr.name, cr.scheme, len(cr.instances))
		for _, inst := range cr.instances {
			log.Info("[Relay]     upstream %s:%d (weight=%d)",
				inst.host, inst.port, inst.weight)
		}
	}
	return rs, nil
}

// buildServer turns a config Server into runtime state, registering each
// instance as a peer on the NHP device.
func (rs *RelayServer) buildServer(c *Server) (*serverRuntime, error) {
	pubKey, err := base64.StdEncoding.DecodeString(c.PubKeyBase64)
	if err != nil {
		return nil, fmt.Errorf("relay: server %q invalid publicKeyBase64: %w", c.Name, err)
	}
	id := utils.PubKeyFingerprint(pubKey)

	sticky := false // default: per-request load balancing
	if c.StickyInstance != nil {
		sticky = *c.StickyInstance
	}
	cr := &serverRuntime{
		id:           id,
		name:         c.Name,
		pubKey:       pubKey,
		pubKeyBase64: c.PubKeyBase64,
		scheme:       c.LoadBalance,
		sticky:       sticky,
		instances:    make([]*serverInstance, 0, len(c.Instances)),
	}

	for j := range c.Instances {

View on GitHub (pinned to 6e04ca5ff0)