fatedier/frp · error · configmgmt.ErrApplyConfig

apply config failed: failed to apply config: %v

Error message

apply config failed: failed to apply config: %v

What it means

After a store mutation succeeds, withStoreMutationAndReload calls reloadConfigFromSourcesLocked to apply the new combined config (file source + store source) to the running client. If that reload fails, the mutation is kept in the store but is not running, and the error is wrapped with configmgmt.ErrApplyConfig. Reload failures come from validation/initialization of the aggregated config.

Source

Thrown at client/config_manager.go:385

}

func (m *serviceConfigManager) withStoreMutationAndReload(
	fn func(storeSource *source.StoreSource) error,
) error {
	m.svr.reloadMu.Lock()
	defer m.svr.reloadMu.Unlock()

	storeSource := m.svr.storeSource
	if storeSource == nil {
		return fmt.Errorf("%w: store API is disabled", configmgmt.ErrStoreDisabled)
	}

	if err := fn(storeSource); err != nil {
		return err
	}

	if err := m.svr.reloadConfigFromSourcesLocked(); err != nil {
		return fmt.Errorf("%w: failed to apply config: %v", configmgmt.ErrApplyConfig, err)
	}
	return nil
}

func (m *serviceConfigManager) withStoreProxyMutationAndReload(
	name string,
	fn func(storeSource *source.StoreSource) error,
) (v1.ProxyConfigurer, error) {
	m.svr.reloadMu.Lock()
	defer m.svr.reloadMu.Unlock()

	storeSource := m.svr.storeSource
	if storeSource == nil {
		return nil, fmt.Errorf("%w: store API is disabled", configmgmt.ErrStoreDisabled)
	}

	if err := fn(storeSource); err != nil {
		return nil, err

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Inspect the wrapped %v to see which config entry failed re-validation
  2. Resolve the conflict (rename the colliding proxy or change bindPort) — check both frpc.toml and the store contents
  3. Call GET /api/reload after fixing; the store keeps your mutation, so a successful reload brings it live
  4. Avoid defining the same proxy both in the config file and through the store API
Defensive patterns

Strategy: try-catch

Try / catch

if resp.StatusCode == http.StatusInternalServerError {
	// store mutated but reload failed: read detail, fix conflict, then GET /api/reload
}

Prevention

When it happens

Trigger: Create/update/delete via store API where re-validating all proxies/visitors (file + store) fails after the write — e.g. duplicate proxy names between file config and store, or a combined config that no longer passes client validation.

Common situations: A proxy in frpc.toml and a store-created proxy collide on name or bind port; partial upgrade where an old config becomes invalid under stricter new-version validation; the mutation itself succeeded so the store and running state have diverged until the next successful reload.

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/3118f24df1f20b72. Report an issue: GitHub.