{"record":{"id":"ead96751222b3405","repo":"fatedier/frp","slug":"errnotfound","errorCode":"ErrNotFound","errorMessage":"not found","messagePattern":"not found","errorType":"error_code","errorClass":null,"httpStatus":404,"severity":"error","filePath":"client/configmgmt/types.go","lineNumber":13,"sourceCode":"package configmgmt\n\nimport (\n\t\"errors\"\n\t\"time\"\n\n\t\"github.com/fatedier/frp/client/proxy\"\n\tv1 \"github.com/fatedier/frp/pkg/config/v1\"\n)\n\nvar (\n\tErrInvalidArgument = errors.New(\"invalid argument\")\n\tErrNotFound        = errors.New(\"not found\")\n\tErrConflict        = errors.New(\"conflict\")\n\tErrStoreDisabled   = errors.New(\"store disabled\")\n\tErrApplyConfig     = errors.New(\"apply config failed\")\n)\n\ntype ConfigManager interface {\n\tReloadFromFile(strict bool) error\n\n\tReadConfigFile() (string, error)\n\tWriteConfigFile(content []byte) error\n\n\tGetProxyStatus() []*proxy.WorkingStatus\n\tIsStoreProxyEnabled(name string) bool\n\tStoreEnabled() bool\n\n\tGetProxyConfig(name string) (v1.ProxyConfigurer, bool)\n\tGetVisitorConfig(name string) (v1.VisitorConfigurer, bool)\n","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/client/configmgmt/types.go#L1-L31","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["List all proxies/visitors (GetProxyStatus or GET /api/proxy) and confirm the exact name spelling","If the entry lives in the config file rather than the store, edit the file or reload instead of using store APIs","Treat errors.Is(err, configmgmt.ErrNotFound) on delete as idempotent success in automation","Check the store path still contains the expected entries when the store source is enabled"],"exampleFix":"// before\nif err := mgr.DeleteProxy(ctx, \"ssh\"); err != nil { return err } // not found: proxy \"ssh\"\n\n// after\nerr := mgr.DeleteProxy(ctx, \"ssh\")\nif err != nil && errors.Is(err, configmgmt.ErrNotFound) {\n    return nil // already gone — idempotent delete\n} else if err != nil {\n    return err\n}","handlingStrategy":"validation","validationCode":"if _, err := mgr.GetProxy(ctx, name); err != nil {\n    if errors.Is(err, configmgmt.ErrNotFound) {\n        // name absent — create instead of update, or 404 early\n    }\n}","typeGuard":null,"tryCatchPattern":"err := mgr.DeleteProxy(ctx, name)\nswitch {\ncase err == nil:\ncase errors.Is(err, configmgmt.ErrNotFound):\n    err = nil // idempotent delete\n}","preventionTips":["List names before referencing them; copy exact spelling","Make deletes idempotent by swallowing ErrNotFound in automation","Remember file-defined and store-defined entries share one name namespace"],"tags":["go","frpc","config-management","not-found","admin-api"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}