{"record":{"id":"bc20b7d8e7fc66c4","repo":"OpenNHP/opennhp","slug":"config-load-error-bc20b7","errorCode":null,"errorMessage":"config load error","messagePattern":"config load error","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"endpoints/db/config.go","lineNumber":23,"sourceCode":"\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\n\ttoml \"github.com/pelletier/go-toml/v2\"\n\n\t\"github.com/OpenNHP/opennhp/nhp/common/clusterconfig\"\n\t\"github.com/OpenNHP/opennhp/nhp/core\"\n\t\"github.com/OpenNHP/opennhp/nhp/log\"\n\t\"github.com/OpenNHP/opennhp/nhp/utils\"\n)\n\nvar (\n\tbaseConfigWatch     io.Closer\n\tserverConfigWatch   io.Closer\n\tteesConfigWatch     io.Closer\n\tresourceConfigWatch io.Closer\n\n\terrLoadConfig = fmt.Errorf(\"config load error\")\n)\n\ntype Config struct {\n\tLogLevel            int\n\tPrivateKeyBase64    string\n\tDefaultCipherScheme int    `json:\"defaultCipherScheme\"`\n\tSymmetricCipherMode string `json:\"symmetricCipherMode\"`\n\tDbId                string `json:\"dbId\"`\n}\n\n// Peers is the top-level shape of server.toml. Each entry is one\n// logical nhp-server identity (one pubkey) reachable at 1..N instances\n// — same schema as nhp-agent's and nhp-ac's server.toml (see\n// nhp/common/clusterconfig). nhp-db only ever talks to a single\n// instance per cluster today, so LoadBalance / StickyInstance are\n// loaded but ignored; the schema is shared so operators don't need a\n// per-daemon dialect.\ntype Peers struct {","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/db/config.go#L5-L41","documentation":"errLoadConfig is a package-level sentinel error in endpoints/db/config.go (mirrored by endpoints/ac/config.go) returned whenever the daemon's base/server/tees/resource config load or watch-update fails. It is also used as the panic-recovery value in updateBaseConfig, so any panic during a config reload is reported as this generic error. Because it is a plain sentinel, the underlying cause must be found in logs.","triggerScenarios":"LoadConfig or updateBaseConfig fails: malformed/unreadable config.toml/server.toml/tees.toml/resource.toml, watch callback panics (recovered and converted to errLoadConfig), or type-conversion failures while parsing fields like LogLevel.","commonSituations":"TOML file edited by hand with syntax errors; missing config file at startup; wrong field types (string where int expected); etcd/file watcher delivering a partially written file that panics the parser; permissions changed on etc/ directory.","solutions":["Validate each TOML file in etc/ (config.toml, server.toml, tees.toml, resource.toml) parses correctly.","Check daemon logs immediately before the error for the real parse/watch failure.","Restore file permissions and ensure the daemon user can read all config files.","Compare configs against the shipped templates in endpoints/*/etc/ for field names and types.","If triggered by a watch update, fix the last written change or redeploy the previous known-good config."],"exampleFix":"// before: panic swallowed into generic sentinel\nutils.CatchPanicThenRun(func() {\n    err = errLoadConfig\n})\n\n// after: record the concrete cause too\nutils.CatchPanicThenRun(func() {\n    log.Error(\"panic during config update: %v\", recover())\n    err = fmt.Errorf(\"config load error: %w\", errLoadConfig)\n})","handlingStrategy":"validation","validationCode":"for _, f := range []string{\"config.toml\", \"server.toml\", \"tees.toml\", \"resource.toml\"} {\n    if _, err := toml.ParseFile(filepath.Join(etcDir, f)); err != nil {\n        log.Fatalf(\"config %s invalid: %v\", f, err)\n    }\n}","typeGuard":"func configReadable(dir string) bool {\n    for _, f := range requiredConfigFiles {\n        if fi, err := os.Stat(filepath.Join(dir, f)); err != nil || fi.IsDir() { return false }\n    }\n    return true\n}","tryCatchPattern":"if err := ac.LoadConfig(); err != nil {\n    if errors.Is(err, errLoadConfig) {\n        log.Fatalf(\"config load failed — inspect logs and etc/*.toml: %v\", err)\n    }\n    return err\n}","preventionTips":["Validate TOML files in CI before deploying configs.","Write config updates atomically (temp file + rename) so watchers never parse partial files.","Run the daemon as a user with read access to the etc/ directory.","Diff live configs against shipped templates after upgrades."],"tags":["config","toml","startup","nhp-db"],"backgroundTag":"config-file-not-found","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}