fatedier/frp · error · configmgmt.ErrStoreDisabled

store disabled: store API is disabled

Error message

store disabled: store API is disabled

What it means

storeSourceOrError returns configmgmt.ErrStoreDisabled when the running frpc has no store source attached. The store exists only if common.store.enabled is true in the client config (cmd/frpc/sub/root.go:145 creates it); otherwise svr.storeSource stays nil and every read of store state fails. Maps to HTTP 404 in the admin controller.

Source

Thrown at client/config_manager.go:364

	}); err != nil {
		return err
	}

	log.Infof("store: deleted visitor %q", name)
	return nil
}

func (m *serviceConfigManager) GracefulClose(d time.Duration) {
	m.svr.GracefulClose(d)
}

func (m *serviceConfigManager) storeSourceOrError() (*source.StoreSource, error) {
	m.svr.reloadMu.Lock()
	storeSource := m.svr.storeSource
	m.svr.reloadMu.Unlock()

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

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
	}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Enable the store in frpc config: set [store] enabled = true (and optionally path)
  2. Restart frpc so NewStoreSource is created and attached to the aggregator
  3. If storePath creation fails at startup, fix the path/permissions — startup error 'failed to create store source' means the API stays disabled
  4. Without a store, manage config by editing the file and calling GET /api/reload

Example fix

# frpc.toml — before
[webServer]
port = 7400

# after
[webServer]
port = 7400

[store]
enabled = true
path = "./frpc_store.db"
Defensive patterns

Strategy: validation

Validate before calling

func storeEnabled(cfgPath string) (bool, error) {
	b, err := os.ReadFile(cfgPath)
	if err != nil {
		return false, err
	}
	return strings.Contains(string(b), "[store]"), nil // or parse with frp config loader
}

Prevention

When it happens

Trigger: Any store read API (e.g. GET /api/config/proxies, GET /api/config/visitors) called while frpc runs without [store] enabled in its config file.

Common situations: Enabling the admin API (webServer.port) but forgetting the store section; expecting the admin API to manage file-configured proxies; config drift between environments where store is only enabled on some hosts.

Related errors


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