{"record":{"id":"f38ae87207dfdb9a","repo":"fatedier/frp","slug":"apply-config-failed-proxy-q-not-found-in-store-a","errorCode":null,"errorMessage":"apply config failed: proxy %q not found in store after mutation","messagePattern":"apply config failed: proxy %q not found in store after mutation","errorType":"http","errorClass":"configmgmt.ErrApplyConfig","httpStatus":500,"severity":"error","filePath":"client/config_manager.go","lineNumber":411,"sourceCode":") (v1.ProxyConfigurer, error) {\n\tm.svr.reloadMu.Lock()\n\tdefer m.svr.reloadMu.Unlock()\n\n\tstoreSource := m.svr.storeSource\n\tif storeSource == nil {\n\t\treturn nil, fmt.Errorf(\"%w: store API is disabled\", configmgmt.ErrStoreDisabled)\n\t}\n\n\tif err := fn(storeSource); err != nil {\n\t\treturn nil, err\n\t}\n\tif err := m.svr.reloadConfigFromSourcesLocked(); err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: failed to apply config: %v\", configmgmt.ErrApplyConfig, err)\n\t}\n\n\tpersisted := storeSource.GetProxy(name)\n\tif persisted == nil {\n\t\treturn nil, fmt.Errorf(\"%w: proxy %q not found in store after mutation\", configmgmt.ErrApplyConfig, name)\n\t}\n\treturn persisted.Clone(), nil\n}\n\nfunc (m *serviceConfigManager) withStoreVisitorMutationAndReload(\n\tname string,\n\tfn func(storeSource *source.StoreSource) error,\n) (v1.VisitorConfigurer, error) {\n\tm.svr.reloadMu.Lock()\n\tdefer m.svr.reloadMu.Unlock()\n\n\tstoreSource := m.svr.storeSource\n\tif storeSource == nil {\n\t\treturn nil, fmt.Errorf(\"%w: store API is disabled\", configmgmt.ErrStoreDisabled)\n\t}\n\n\tif err := fn(storeSource); err != nil {\n\t\treturn nil, err","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/client/config_manager.go#L393-L429","documentation":"After a proxy mutation and successful reload, withStoreProxyMutationAndReload re-reads the proxy from the store; if GetProxy returns nil it fails with ErrApplyConfig. This is an internal consistency check — the proxy that was just written is no longer readable, meaning the store write did not stick or the store was mutated concurrently.","triggerScenarios":"Rare race: another writer (a second admin API call, or an external process touching the store file at common.store.path) removes/renames the proxy between the mutation and the read-back; or the store backend silently dropped the write.","commonSituations":"Concurrent API calls from multiple automation tools; store file on flaky storage; two frpc instances pointed at the same store file.","solutions":["Retry the operation once (likely transient race)","Serialize store mutations with a lock in your automation so only one writer runs at a time","Verify only one frpc process uses the store path","Check store file health/permissions on disk"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Serialize store mutations with a mutex/single writer","Run only one frpc per store file","Retry once — this is an internal read-back race"],"tags":["frp","frpc","config-store","race-condition","internal"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}