fatedier/frp · error

ErrNotFound

ErrNotFound

Error message

not found

What it means

configmgmt.ErrNotFound is the frpc config-manager sentinel for absent resources. GetProxy/GetVisitor wrap it as 'not found: proxy "<name>"' when no configurer with that name is loaded, and update/delete paths wrap store errors with it when the target does not exist in the store source. The admin HTTP layer maps it to 404 (client/http/controller.go:62).

Source

Thrown at client/configmgmt/types.go:13

package configmgmt

import (
	"errors"
	"time"

	"github.com/fatedier/frp/client/proxy"
	v1 "github.com/fatedier/frp/pkg/config/v1"
)

var (
	ErrInvalidArgument = errors.New("invalid argument")
	ErrNotFound        = errors.New("not found")
	ErrConflict        = errors.New("conflict")
	ErrStoreDisabled   = errors.New("store disabled")
	ErrApplyConfig     = errors.New("apply config failed")
)

type ConfigManager interface {
	ReloadFromFile(strict bool) error

	ReadConfigFile() (string, error)
	WriteConfigFile(content []byte) error

	GetProxyStatus() []*proxy.WorkingStatus
	IsStoreProxyEnabled(name string) bool
	StoreEnabled() bool

	GetProxyConfig(name string) (v1.ProxyConfigurer, bool)
	GetVisitorConfig(name string) (v1.VisitorConfigurer, bool)

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. List all proxies/visitors (GetProxyStatus or GET /api/proxy) and confirm the exact name spelling
  2. If the entry lives in the config file rather than the store, edit the file or reload instead of using store APIs
  3. Treat errors.Is(err, configmgmt.ErrNotFound) on delete as idempotent success in automation
  4. Check the store path still contains the expected entries when the store source is enabled

Example fix

// before
if err := mgr.DeleteProxy(ctx, "ssh"); err != nil { return err } // not found: proxy "ssh"

// after
err := mgr.DeleteProxy(ctx, "ssh")
if err != nil && errors.Is(err, configmgmt.ErrNotFound) {
    return nil // already gone — idempotent delete
} else if err != nil {
    return err
}
Defensive patterns

Strategy: validation

Validate before calling

if _, err := mgr.GetProxy(ctx, name); err != nil {
    if errors.Is(err, configmgmt.ErrNotFound) {
        // name absent — create instead of update, or 404 early
    }
}

Try / catch

err := mgr.DeleteProxy(ctx, name)
switch {
case err == nil:
case errors.Is(err, configmgmt.ErrNotFound):
    err = nil // idempotent delete
}

Prevention

When it happens

Trigger: GET /api/proxy/{name} or /api/visitor/{name} for a name that is not in the loaded config; DELETE or PUT on a store-managed proxy/visitor whose name was never created or was already deleted.

Common situations: Dashboard or automation referencing a proxy renamed or removed in the config file; deleting the same proxy twice; name casing/whitespace mismatch between URL and stored name; store file wiped or reset so previously created entries vanished.

Related errors


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