{"record":{"id":"1b501f010240ca2f","repo":"OpenNHP/opennhp","slug":"relay-failed-to-read-config-s-w","errorCode":null,"errorMessage":"relay: failed to read config %s: %w","messagePattern":"relay: failed to read config (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"endpoints/relay/config.go","lineNumber":157,"sourceCode":"\t}\n}\n\n// LoadConfig reads a TOML config file.  If path is empty it defaults to\n// etc/config.toml relative to ExeDirPath.\nfunc LoadConfig(path string) (*Config, error) {\n\tcfg := DefaultConfig()\n\n\tif path == \"\" {\n\t\tpath = filepath.Join(ExeDirPath, \"etc\", \"config.toml\")\n\t}\n\n\tdata, err := os.ReadFile(path)\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\tlog.Warning(\"[Relay] config file %s not found, using defaults\", path)\n\t\t\treturn cfg, nil\n\t\t}\n\t\treturn nil, fmt.Errorf(\"relay: failed to read config %s: %w\", path, err)\n\t}\n\n\tif err := toml.Unmarshal(data, cfg); err != nil {\n\t\treturn nil, fmt.Errorf(\"relay: failed to parse config %s: %w\", path, err)\n\t}\n\n\tif err := cfg.normalize(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tlog.Info(\"[Relay] loaded config from %s with %d server(s)\", path, len(cfg.Servers))\n\treturn cfg, nil\n}\n\n// normalize validates the configuration and applies legacy-field migration so\n// that the rest of the relay only has to look at Config.Servers. It is\n// exported as a method (not a function) to make it directly testable on a\n// hand-built Config in unit tests without round-tripping through TOML.","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/relay/config.go#L139-L175","documentation":"Raised by relay LoadConfig when os.ReadFile on the config path (the given path, or etc/config.toml under the executable directory) fails with an error other than not-exist — typically a permission problem, an unreadable directory, or an I/O error. A missing file is handled separately with a warning and defaults; this error means the file exists but cannot be read.","triggerScenarios":"Thrown at endpoints/relay/config.go:157 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Check file permissions on the config path (chmod/chown so the relay process can read it)","Confirm the path points to a regular file, not a directory or broken symlink","If SELinux/AppArmor is enforced, allow the service to read its etc directory","Fix the underlying I/O issue (disk, mount) if that is the cause"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}