fatedier/frp · error
failed to create store source
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.
Solutions
- Check the resolved store path: if relative it joins filepath.Dir(cfgFile); confirm the directory exists and frpc can write to it.
- Fix permissions or pre-create the directory, or point store.path to an absolute writable location.
- If a stale or corrupt cache file is the cause (parse error inside), delete it; the store is a cache and will be rebuilt.
- 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
- Use absolute store paths in service deployments
- Pre-create and permission the store directory for the frpc user
- Container setups: mount a writable volume at the store path
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
- ErrAlreadyExists
- failed to load config from sources
- include: directory of
- include: parse directory of
- path is required
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/e11090d27b6e463d.
Report an issue: GitHub.
Appendix: 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)