fatedier/frp · error

invalid pool count %d, must be non-negative

Error message

invalid pool count %d, must be non-negative

What it means

NewControl validates the login message from frpc: LoginMsg.PoolCount must be non-negative. A negative pool count is a malformed request, so control creation is refused before any resources are allocated.

Source

Thrown at server/control.go:438

	lifecycleMu    sync.Mutex
	state          controlState
	activated      bool
	handoffBarrier <-chan struct{}

	interruptOnce sync.Once
	interruptErr  error

	mu sync.RWMutex

	xl            *xlog.Logger
	ctx           context.Context
	doneCh        chan struct{}
	serverMetrics metrics.ServerMetrics
}

func NewControl(ctx context.Context, sessionCtx *SessionContext) (*Control, error) {
	if sessionCtx.LoginMsg.PoolCount < 0 {
		return nil, fmt.Errorf("invalid pool count %d, must be non-negative", sessionCtx.LoginMsg.PoolCount)
	}
	if sessionCtx.ServerCfg.Transport.MaxPoolCount < 0 {
		return nil, fmt.Errorf(
			"invalid max pool count %d, must be non-negative",
			sessionCtx.ServerCfg.Transport.MaxPoolCount,
		)
	}
	effectivePoolCount := min(int64(sessionCtx.LoginMsg.PoolCount), sessionCtx.ServerCfg.Transport.MaxPoolCount)
	maxPoolCountForChannel := int64(math.MaxInt) - int64(workConnPoolCapacityOffset)
	if effectivePoolCount > maxPoolCountForChannel {
		return nil, fmt.Errorf(
			"invalid effective pool count %d, cannot safely add %d for work connection pool capacity",
			effectivePoolCount, workConnPoolCapacityOffset,
		)
	}
	poolCount := int(effectivePoolCount)
	ctl := &Control{
		sessionCtx:    sessionCtx,

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. If you write a custom client, always send a zero-or-positive PoolCount (0 means create work conns on demand).
  2. Inspect the raw login frame (enable trace logging on frps) to find who sends a negative value.
  3. Upgrade mismatched frpc builds to a released version.

Example fix

// custom client — before
loginMsg.PoolCount = -1

// after
loginMsg.PoolCount = 0
Defensive patterns

Strategy: validation

Validate before calling

// custom client before login
if loginMsg.PoolCount < 0 { loginMsg.PoolCount = 0 }

Try / catch

if _, err := server.NewControl(ctx, sessionCtx); err != nil {
    return err // malformed login: reject session, do not retry unchanged
}

Prevention

When it happens

Trigger: A client sends a Login message with PoolCount < 0 — only possible from a hand-rolled or corrupted client, since stock frpc always sends >= 0. Also reachable from unit tests or custom clients built against the msg package.

Common situations: Custom clients/replays with wrong field types; integer underflow in generated login messages; fuzzing the login endpoint; protocol deserialization bugs in third-party clients.

Related errors


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