OpenNHP/opennhp · error

config load error

Error message

config load error

What it means

errLoadConfig is a sentinel error returned by UdpAC.updateBaseConfig and UdpAC.updateHttpConfig when a config reload callback panics; utils.CatchPanicThenRun recovers the panic and the named return err is set to errLoadConfig so callers see a config load failure instead of a crash. It signals that a config file (base, http, or server peer) could not be applied.

Solutions

  1. Inspect ac logs immediately preceding the panic to find the actual panic value and stack from utils.CatchPanicThenRun
  2. Validate the TOML files (config.toml, http.toml) types and required fields before saving; restart nhp-ac with known-good config
  3. Fix the reload code to validate Config fields before mutating live state, so bad files return a normal error instead of panicking
  4. Check for a race between the file watcher and readers sharing the config struct; add locking or snapshot swap

Example fix

// before
func (a *UdpAC) updateBaseConfig(conf Config) (err error) {
	utils.CatchPanicThenRun(func() { err = errLoadConfig })
	...
}
// after
func (a *UdpAC) updateBaseConfig(conf Config) (err error) {
	if conf.ListenAddress == "" || conf.PrivateKeyBase64 == "" {
		return fmt.Errorf("invalid base config: missing required fields")
	}
	utils.CatchPanicThenRun(func() { err = errLoadConfig })
	...
}
Defensive patterns

Strategy: try-catch

Validate before calling

// validate TOML before save
var c ac.Config
if _, err := toml.DecodeFile("config.toml", &c); err != nil { return err }
if c.ListenAddress == "" || c.PrivateKeyBase64 == "" { return fmt.Errorf("config.toml incomplete") }

Try / catch

if err := a.UpdateBaseConfig(conf); err != nil {
	if errors.Is(err, ac.ErrLoadConfig) {
		log.Error("config reload panicked; keeping previous config")
	}
}

Prevention

When it happens

Trigger: A panic occurs inside the config-watch/reload code path of updateBaseConfig (endpoints/ac/config.go:242) or updateHttpConfig (endpoints/ac/config.go:278), e.g. nil dereference or type assertion failure while applying a freshly loaded Config/HttpConfig from the TOML watcher.

Common situations: Editing config.toml or http.toml while nhp-ac is running with a value that makes the reload code panic (wrong type in TOML that slips past unmarshal, missing map entries); hot-reload race where the watcher fires with a partially written file.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at endpoints/ac/config.go:26

	"path/filepath"
	"strconv"
	"strings"

	toml "github.com/pelletier/go-toml/v2"

	"github.com/OpenNHP/opennhp/nhp/common/clusterconfig"
	"github.com/OpenNHP/opennhp/nhp/core"
	"github.com/OpenNHP/opennhp/nhp/etcd"
	"github.com/OpenNHP/opennhp/nhp/log"
	"github.com/OpenNHP/opennhp/nhp/utils"
)

var (
	baseConfigWatch io.Closer
	httpConfigWatch io.Closer
	serverPeerWatch io.Closer

	errLoadConfig = fmt.Errorf("config load error")
)

const (
	FilterMode_IPTABLES = iota // 0
	FilterMode_EBPFXDP         // 1
)

// ACEtcdConfig is the remote-config (etcd) shape. Servers carries the
// shared cluster schema so the etcd value is identical to the on-disk
// server.toml. The previous Endpoints-string form lived only on this
// branch and is removed in the AC → ClusterConfig migration; redeploy
// any etcd values written under that schema.
type ACEtcdConfig struct {
	BaseConfig Config
	HttpConfig HttpConfig
	Servers    []*clusterconfig.ClusterConfig
}

View on GitHub (pinned to 6e04ca5ff0)