router-for-me/CLIProxyAPI · error
credential concurrency busy retry max must not be less than
Error message
credential concurrency busy retry max must not be less than busy retry min
What it means
ValidateCredentialConcurrency requires busy-retry-max >= busy-retry-min. The busy-retry window is [min, max]; an inverted window would make the retry scheduler's interval empty or negative, so the configuration is rejected.
Source
Thrown at internal/config/credential_concurrency.go:162
return fmt.Errorf("lifecycle configuration revision must be positive when present")
}
if cfg.ObservationBarrierRevision < 0 {
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 {View on GitHub (pinned to 78f0c4079e)
Solutions
- Swap or re-edit so busy-retry-max >= busy-retry-min (e.g. min 250ms, max 1s).
- If you intended a tight fixed window, set both to the same whole-millisecond value.
- Re-validate the whole block; the sibling positivity and millisecond checks still apply.
Example fix
# before (config.yaml) credential-concurrency: busy-retry-min: 1s busy-retry-max: 250ms # after credential-concurrency: busy-retry-min: 250ms busy-retry-max: 1s
Defensive patterns
Strategy: validation
Validate before calling
// Go: retry window must be ordered.
if cfg.BusyRetryMax < cfg.BusyRetryMin {
return errors.New("busy-retry-max must be >= busy-retry-min")
} Prevention
- Edit min and max together; they form a window.
- For a fixed window set both to the same value.
When it happens
Trigger: config.yaml with 'credential-concurrency:\n busy-retry-min: 1s\n busy-retry-max: 250ms' — max numerically smaller than min.
Common situations: Copying the example and editing only one of the two values; assuming min/max naming was the other way around; scripted config generation sorting values incorrectly.
Related errors
- lifecycle configuration revision must be positive when prese
- observation barrier revision must not be negative
- credential concurrency lifecycle durations must be positive
- credential concurrency limiter durations must be positive
- credential concurrency release max backoff must not be less
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/abae6a7702c61d9d.
Report an issue: GitHub.