fatedier/frp · error · ErrGroupAuthFailed
group auth failed
Error message
group auth failed
What it means
ErrGroupAuthFailed is returned when a proxy joins an existing load-balance group on frps with a mismatched groupKey. The first proxy to bind a group's listener sets the group key; subsequent members (tcp.go:116, http.go:105, tcpmux.go:124, https.go:97) must present the same groupKey, which acts as a shared secret so unrelated clients cannot join someone else's group.
Source
Thrown at server/group/group.go:22
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package group
import (
"errors"
)
var (
ErrGroupAuthFailed = errors.New("group auth failed")
ErrGroupParamsInvalid = errors.New("group params invalid")
ErrListenerClosed = errors.New("group listener closed")
ErrGroupDifferentPort = errors.New("group should have same remote port")
ErrProxyRepeated = errors.New("group proxy repeated")
errGroupStale = errors.New("stale group reference")
)
View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Set identical group and groupKey on every proxy that should join the same load-balance group
- After rotating groupKey, update all member clients — mixed keys split the group and late joiners are rejected
- Check for stray whitespace or quoting differences in groupKey in TOML/YAML
Example fix
# client A [[proxies]] name = "a" type = "tcp" group = "app" groupKey = "correct-horse" # client B — before: groupKey = "battery" -> ErrGroupAuthFailed # after groupKey = "correct-horse"
Defensive patterns
Strategy: validation
Validate before calling
// Before connecting: enforce identical groupKey across members (config management side)
for _, p := range proxiesInGroup("app") {
if p.GroupKey != expectedKey {
return fmt.Errorf("proxy %s groupKey mismatch for group app", p.Name)
}
} Type guard
func isGroupAuthFailed(err error) bool {
return errors.Is(err, group.ErrGroupAuthFailed)
} Try / catch
ln, realPort, err := ctl.tcpGroup.Listen(group, groupKey, addr, port)
if errors.Is(err, group.ErrGroupAuthFailed) {
// groupKey differs from the first member — correct the config before retrying
} Prevention
- Distribute groupKey via your secret manager so all members always share the same value
- Rotate groupKey atomically: take members offline, change all configs, bring them back
When it happens
Trigger: Two [[proxies]] blocks with the same group name but different groupKey values; rolling out a new groupKey to some clients before others; whitespace/typo differences in groupKey between config files.
Common situations: Scaling a group to a second machine and forgetting to copy groupKey; secret rotation done on only part of the fleet; copy-paste between environments (staging key used against prod group).
Related errors
- group params invalid
- group should have same remote port
- exec configuration is required when type is 'exec'
- file path cannot be empty
- send ${op} request to plugin error
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/8123b3e1c9b13c8f.
Report an issue: GitHub.