fatedier/frp · error · ErrApplyConfig
apply config failed: %v
Error message
apply config failed: %v
What it means
Returned by serviceConfigManager.ReloadFromFile when svr.UpdateConfigSource fails while applying the freshly loaded and validated config to the running frpc service — i.e. parsing and validation succeeded but the live swap-in failed. It wraps configmgmt.ErrApplyConfig to distinguish it from ErrInvalidArgument cases.
Source
Thrown at client/config_manager.go:49
result, err := config.LoadClientConfigResult(m.svr.configFilePath, strict)
if err != nil {
return fmt.Errorf("%w: %v", configmgmt.ErrInvalidArgument, err)
}
proxyCfgsForValidation, visitorCfgsForValidation := config.FilterClientConfigurers(
result.Common,
result.Proxies,
result.Visitors,
)
proxyCfgsForValidation = config.CompleteProxyConfigurers(proxyCfgsForValidation)
visitorCfgsForValidation = config.CompleteVisitorConfigurers(visitorCfgsForValidation)
if _, err := validation.ValidateAllClientConfig(result.Common, proxyCfgsForValidation, visitorCfgsForValidation, m.svr.unsafeFeatures); err != nil {
return fmt.Errorf("%w: %v", configmgmt.ErrInvalidArgument, err)
}
if err := m.svr.UpdateConfigSource(result.Common, result.Proxies, result.Visitors); err != nil {
return fmt.Errorf("%w: %v", configmgmt.ErrApplyConfig, err)
}
log.Infof("success reload conf")
return nil
}
func (m *serviceConfigManager) ReadConfigFile() (string, error) {
if m.svr.configFilePath == "" {
return "", fmt.Errorf("%w: frpc has no config file path", configmgmt.ErrInvalidArgument)
}
content, err := os.ReadFile(m.svr.configFilePath)
if err != nil {
return "", fmt.Errorf("%w: %v", configmgmt.ErrInvalidArgument, err)
}
return string(content), nil
}
View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Check the %v detail and frpc logs for which proxy/visitor failed to apply; fix that item (free the local port, correct bindAddr)
- If reload state is wedged, do a full restart of frpc with the new config instead of hot reload
- Verify local ports for visitors/proxies are free on the frpc host (ss -ltnp)
- Keep hot reloads to config-only changes; restart for changes that rebind listeners
Example fix
# before — visitor bindPort 6000 already used locally [[visitors]] name = "stcp-v" type = "stcp" bindAddr = "127.0.0.1" bindPort = 6000 # after bindPort = 6100
Defensive patterns
Strategy: fallback
Validate before calling
// Pre-check local bind ports for visitors/proxies before reload
for _, v := range visitorCfgs {
ln, err := net.Listen("tcp", net.JoinHostPort(v.BindAddr, strconv.Itoa(v.BindPort)))
if err != nil {
return fmt.Errorf("visitor %s cannot bind %s:%d: %v", v.Name, v.BindAddr, v.BindPort, err)
}
ln.Close()
} Type guard
func isApplyConfig(err error) bool {
return errors.Is(err, configmgmt.ErrApplyConfig)
} Try / catch
if err := configManager.ReloadFromFile(true); err != nil {
if errors.Is(err, configmgmt.ErrApplyConfig) {
// config is valid but could not be applied live: fall back to a full frpc restart with the new file
}
} Prevention
- Free or change local ports that listeners will bind before hot-reload
- For changes that rebind listeners, prefer a supervised restart over hot reload
When it happens
Trigger: Reloading a config whose proxies/visitors cannot be brought up at runtime (e.g. binding a local port already in use on the frpc host, or a listener type the running service cannot restart); internal state-transition failures inside the client service during hot reload.
Common situations: Hot-reload after editing bindAddr/bindPort of visitors to a port occupied by another process on the frpc machine; reloading while the previous config's proxies are mid-teardown; resource limits preventing new listeners.
Related errors
- invalid argument: frpc has no config file path
- invalid argument: %v
- apply config failed: failed to apply config: %v
- VirtualNet-dependent configuration requires a VirtualNet run
- ErrAlreadyExists
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/7bcd652dfca75dad.
Report an issue: GitHub.