jackc/pgx · error

invalid SCRAM server-first-message received from server: did

Error message

invalid SCRAM server-first-message received from server: did not include i=

What it means

Returned by recvServerFirstMessage when the salt attribute is present but no comma separator follows it, so the iteration-count attribute 'i=' cannot be located. RFC 5802 requires i= after s=.

Source

Thrown at pgconn/auth_scram.go:266

		return errors.New("invalid SCRAM server-first-message received from server: did not include r=")
	}
	buf = buf[2:]

	idx := bytes.IndexByte(buf, ',')
	if idx == -1 {
		return errors.New("invalid SCRAM server-first-message received from server: did not include s=")
	}
	sc.clientAndServerNonce = buf[:idx]
	buf = buf[idx+1:]

	if !bytes.HasPrefix(buf, []byte("s=")) {
		return errors.New("invalid SCRAM server-first-message received from server: did not include s=")
	}
	buf = buf[2:]

	idx = bytes.IndexByte(buf, ',')
	if idx == -1 {
		return errors.New("invalid SCRAM server-first-message received from server: did not include i=")
	}
	saltStr := buf[:idx]
	buf = buf[idx+1:]

	if !bytes.HasPrefix(buf, []byte("i=")) {
		return errors.New("invalid SCRAM server-first-message received from server: did not include i=")
	}
	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 {

View on GitHub (pinned to ec1a0befd2)

Solutions

  1. Confirm a genuine, conformant PostgreSQL backend.
  2. Remove protocol-rewriting intermediaries.
  3. Capture and inspect the raw payload, then report the malformed message source.
Defensive patterns

Strategy: try-catch

Try / catch

if err := connect(); err != nil && strings.Contains(err.Error(), "did not include i=") {
    return fmt.Errorf("malformed SCRAM iteration count from server: %w", err)
}

Prevention

When it happens

Trigger: Server sends 'r=...,s=base64salt' with no trailing comma/iteration count. Same malformed-message class as the other server-first parse errors.

Common situations: Truncated/malformed SASL payloads from a buggy server or proxy; MITM corruption.

Related errors


AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04). Data as JSON: /data/errors/15a7c78e996ff6e9.json. Report an issue: GitHub.