jackc/pgx · error
SCRAM iteration count from server too high
Error message
SCRAM iteration count from server too high: %d (max %d)
What it means
The server's SCRAM iteration count exceeds the client's safety ceiling. This guard prevents a malicious server from forcing the client to burn unbounded CPU in PBKDF2 derivation. PostgreSQL defaults to 4096 iterations; values far above that are rejected.
Solutions
- Check the server's scram_iterations setting; reset it to a sane value (e.g. 4096)
- Verify you are connecting to a trusted server
- Do not blindly raise the client limit; the server may be malicious
- Report the server configuration to your DBA
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at pgconn/auth_scram.go:292 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04).
Data as JSON: /api/errors/05407baaf8d26eb2.
Report an issue: GitHub.
Appendix: source
Thrown at pgconn/auth_scram.go:292
buf = buf[2:]
iterationsStr := buf
var err error
sc.salt, err = base64.StdEncoding.DecodeString(string(saltStr))
if err != nil {
return fmt.Errorf("invalid SCRAM salt received from server: %w", err)
}
sc.iterations, err = strconv.Atoi(string(iterationsStr))
if err != nil || sc.iterations <= 0 {
return fmt.Errorf("invalid SCRAM iteration count received from server: %w", err)
}
// Bound server-supplied iteration count to prevent a malicious server from forcing the client
// to spend unbounded CPU in PBKDF2. PostgreSQL's scram_iterations defaults to 4096; this ceiling
// is ~2500x that.
const maxScramIterations = 10_000_000
if sc.iterations > maxScramIterations {
return fmt.Errorf("SCRAM iteration count from server too high: %d (max %d)", sc.iterations, maxScramIterations)
}
if !bytes.HasPrefix(sc.clientAndServerNonce, sc.clientNonce) {
return errors.New("invalid SCRAM nonce: did not start with client nonce")
}
if len(sc.clientAndServerNonce) <= len(sc.clientNonce) {
return errors.New("invalid SCRAM nonce: did not include server nonce")
}
return nil
}
func (sc *scramClient) clientFinalMessage() string {
// The c= attribute carries the base64-encoded channel binding input.
//
// Without channel binding this is just the GS2 header alone ("biws" for
// "n,," or "eSws" for "y,,").View on GitHub (pinned to ec1a0befd2)