fatedier/frp · error
path is required
Error message
path is required
What it means
NewStoreSource constructs the dynamic store-backed config source (used for API-managed proxies/visitors persisted to a JSON file). StoreSourceConfig has a single Path field; constructing with an empty Path returns 'path is required' before anything is read. A non-existent file is fine (it is created lazily), but no path at all is a programming error.
Source
Thrown at pkg/config/source/store.go:53
type StoreSource struct {
baseSource
config StoreSourceConfig
}
var (
ErrAlreadyExists = errors.New("already exists")
ErrNotFound = errors.New("not found")
)
const (
storeKindProxy = "proxy"
storeKindVisitor = "visitor"
)
func NewStoreSource(cfg StoreSourceConfig) (*StoreSource, error) {
if cfg.Path == "" {
return nil, fmt.Errorf("path is required")
}
s := &StoreSource{
baseSource: newBaseSource(),
config: cfg,
}
if err := s.loadFromFile(); err != nil {
if !os.IsNotExist(err) {
return nil, fmt.Errorf("failed to load existing data: %w", err)
}
}
return s, nil
}
func (s *StoreSource) loadFromFile() error {
s.mu.Lock()View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Set cfg.Path to a writable file location (e.g. /var/lib/frp/store.json)
- Ensure the frpc process user can create/write that path (parent dir exists, correct ownership)
- If constructing programmatically, fail fast on empty Path before calling NewStoreSource
Example fix
// before
src, err := source.NewStoreSource(source.StoreSourceConfig{})
// after
src, err := source.NewStoreSource(source.StoreSourceConfig{Path: "/var/lib/frp/store.json"}) Defensive patterns
Strategy: validation
Validate before calling
if cfg.Path == "" { return nil, errors.New("StoreSourceConfig.Path must be set (e.g. /var/lib/frp/store.json)") }
if dir := filepath.Dir(cfg.Path); dir != "" { if _, err := os.Stat(dir); err != nil { os.MkdirAll(dir, 0o755) } } Type guard
func hasStorePath(cfg source.StoreSourceConfig) bool { return strings.TrimSpace(cfg.Path) != "" } Try / catch
src, err := source.NewStoreSource(cfg)
if err != nil {
if err.Error() == "path is required" { /* fill cfg.Path from flag/env with a sane default and retry construction */ }
return err
} Prevention
- Default the store path in your app's flag parsing (e.g. --store-path with default)
- Fail fast on empty path at CLI parsing time
- Ensure the store directory is writable by the service user
When it happens
Trigger: Calling source.NewStoreSource(source.StoreSourceConfig{Path: ""}) — e.g. the path flag was not parsed, was typo'd, or the config struct was zero-valued when wiring the aggregator.
Common situations: Embedding frp as a library and wiring a store source; config-flag parsing that silently drops the store path (typo'd flag name) leading to an empty string at construction.
Related errors
- ErrAlreadyExists
- localAddr is required
- localPath is required
- unixPath is required
- name should not be empty
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/81fff507726c6927.
Report an issue: GitHub.