fatedier/frp · error

failed to create store source: %w

Error message

failed to create store source: %w

What it means

The client store feature is enabled (common.store) but source.NewStoreSource failed while preparing the on-disk cache at the resolved store path. The path is joined with the config file's directory when relative, so failure usually means the filesystem location is unusable.

Source

Thrown at cmd/frpc/sub/root.go:155

func runClientWithAggregator(result *config.ClientConfigLoadResult, unsafeFeatures *security.UnsafeFeatures, cfgFilePath string) error {
	configSource := source.NewConfigSource()
	if err := configSource.ReplaceAll(result.Proxies, result.Visitors); err != nil {
		return fmt.Errorf("failed to set config source: %w", err)
	}

	var storeSource *source.StoreSource

	if result.Common.Store.IsEnabled() {
		storePath := result.Common.Store.Path
		if storePath != "" && cfgFilePath != "" && !filepath.IsAbs(storePath) {
			storePath = filepath.Join(filepath.Dir(cfgFilePath), storePath)
		}

		s, err := source.NewStoreSource(source.StoreSourceConfig{
			Path: storePath,
		})
		if err != nil {
			return fmt.Errorf("failed to create store source: %w", err)
		}
		storeSource = s
	}

	aggregator := source.NewAggregator(configSource)
	if storeSource != nil {
		aggregator.SetStoreSource(storeSource)
	}

	proxyCfgs, visitorCfgs, err := aggregator.Load()
	if err != nil {
		return fmt.Errorf("failed to load config from sources: %w", err)
	}

	proxyCfgs, visitorCfgs = config.FilterClientConfigurers(result.Common, proxyCfgs, visitorCfgs)
	proxyCfgs = config.CompleteProxyConfigurers(proxyCfgs)
	visitorCfgs = config.CompleteVisitorConfigurers(visitorCfgs)

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Check the resolved store path: if relative it joins filepath.Dir(cfgFile); confirm the directory exists and frpc can write to it.
  2. Fix permissions or pre-create the directory, or point store.path to an absolute writable location.
  3. If a stale or corrupt cache file is the cause (parse error inside), delete it; the store is a cache and will be rebuilt.
  4. If you don't need offline config caching, disable common.store.

Example fix

# before (frpc.toml)
[store]
enabled = true
path = "/var/frpc/cache"   # parent dir missing

# after
[store]
enabled = true
path = "/var/frpc/cache/frpc_cache"  # mkdir -p /var/frpc/cache first
Defensive patterns

Strategy: validation

Validate before calling

if result.Common.Store.IsEnabled() {
    p := result.Common.Store.Path
    if !filepath.IsAbs(p) {
        p = filepath.Join(filepath.Dir(cfgFilePath), p)
    }
    if f, err := os.OpenFile(p, os.O_RDWR|os.O_CREATE, 0o600); err != nil {
        return fmt.Errorf("store path not writable: %w", err)
    } else {
        f.Close()
    }
}

Prevention

When it happens

Trigger: NewStoreSource errors on an unwritable or nonexistent directory for the store file, a path that exists but has wrong type or permissions, or an unparsable existing store file at that path.

Common situations: store.path points to a location frpc cannot write (read-only volume, missing directory, permissions); relative store.path resolved against an unexpected cfgFile directory; a corrupted or hand-edited cache file from a previous version.

Related errors


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