router-for-me/CLIProxyAPI · error

credential concurrency max limit must be between 1 and %d

Error message

credential concurrency max limit must be between 1 and %d

What it means

ValidateCredentialConcurrency bounds 'credential-concurrency.max-limit' to [1, maxCredentialConcurrencyLimit]. The limit caps concurrent requests per credential; zero, negative, or astronomically large values are rejected. Note the normalization step: if the key is absent, MaxLimit defaults to the ceiling — so this error only fires when the key is present with an out-of-range value (0 or below, or above the hard cap).

Source

Thrown at internal/config/credential_concurrency.go:165

		return fmt.Errorf("observation barrier revision must not be negative")
	}
	if cfg.CPAHeartbeatTimeout <= 0 || cfg.CPACancelBound <= 0 || cfg.ReclaimGrace <= 0 || cfg.CleanupInterval <= 0 {
		return fmt.Errorf("credential concurrency lifecycle durations must be positive")
	}
	if cfg.ReleaseFlushInterval <= 0 || cfg.ReleaseMaxBackoff <= 0 || cfg.BusyRetryMin <= 0 || cfg.BusyRetryMax <= 0 {
		return fmt.Errorf("credential concurrency limiter durations must be positive")
	}
	if cfg.ReleaseMaxBackoff < cfg.ReleaseFlushInterval {
		return fmt.Errorf("credential concurrency release max backoff must not be less than release flush interval")
	}
	if cfg.BusyRetryMin%time.Millisecond != 0 || cfg.BusyRetryMax%time.Millisecond != 0 {
		return fmt.Errorf("credential concurrency busy retry durations must be whole milliseconds")
	}
	if cfg.BusyRetryMax < cfg.BusyRetryMin {
		return fmt.Errorf("credential concurrency busy retry max must not be less than busy retry min")
	}
	if cfg.MaxLimit < 1 || cfg.MaxLimit > maxCredentialConcurrencyLimit {
		return fmt.Errorf("credential concurrency max limit must be between 1 and %d", maxCredentialConcurrencyLimit)
	}
	return nil
}

// ValidateCredentialConcurrencyLifecycle verifies the Home lifecycle timing safety invariant.
func ValidateCredentialConcurrencyLifecycle(nodeHeartbeatTimeout time.Duration, cfg CredentialConcurrencyConfig) error {
	if nodeHeartbeatTimeout <= 0 {
		return fmt.Errorf("credential concurrency lifecycle durations must be positive")
	}
	if errValidate := ValidateCredentialConcurrency(cfg); errValidate != nil {
		return errValidate
	}
	left, leftOverflow := addCredentialConcurrencyDuration(nodeHeartbeatTimeout, cfg.ReclaimGrace)
	right, rightOverflow := addCredentialConcurrencyDuration(cfg.CPAHeartbeatTimeout, cfg.CPACancelBound)
	if leftOverflow || rightOverflow {
		return fmt.Errorf("credential concurrency lifecycle timing safety invariant overflows")
	}
	if left <= right {

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Remove the max-limit key entirely to get the default hard cap, or set it between 1 and the cap (e.g. max-limit: 1000000).
  2. Never use 0 or negatives to mean 'unlimited'.
  3. Check config.example.yaml line 66 for the allowed ceiling and stay within it.

Example fix

# before (config.yaml)
credential-concurrency:
  max-limit: 0

# after: key removed (defaults to hard cap)
credential-concurrency:
  cpa-heartbeat-timeout: 3s
Defensive patterns

Strategy: validation

Validate before calling

// Go: bound max-limit to the hard cap (mirror of the library check).
const maxCap = int64(1000000) // keep in sync with maxCredentialConcurrencyLimit
if cfg.MaxLimit < 1 || cfg.MaxLimit > maxCap {
    return fmt.Errorf("max-limit must be in [1, %d]", maxCap)
}

Prevention

When it happens

Trigger: config.yaml with 'credential-concurrency:\n max-limit: 0', 'max-limit: -5', or a value above maxCredentialConcurrencyLimit (the hard cap, e.g. 1000000 as shown in config.example.yaml).

Common situations: Setting max-limit: 0 intending 'unlimited' (the ceiling default applies only when the key is absent); scaling values beyond the hard cap to disable throttling; templated configs emitting 0 for unset integers.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/2b7048734e8785b4. Report an issue: GitHub.