ory/kratos · error · ErrHashParametersOutOfBounds
pbkdf2 i= not in [1, ]
Error message
pbkdf2 i=%d not in [1, %d]
What it means
This error means a PBKDF2 hash declares an iteration count i that is 0 or greater than 10,000,000. i=0 does no key-stretching; a huge i makes every password comparison take unbounded CPU time, so the package caps it at ~10x OWASP's strongest published recommendation. It wraps ErrHashParametersOutOfBounds from validatePbkdf2Params during hash decode.
Solutions
- Check the iteration count in the hash string; it must be in [1, 10000000]
- Re-hash with an OWASP 2023 recommendation (600k for SHA-256, 210k for SHA-512)
- For legacy users with higher counts, migrate via rehash-on-login after successful authentication
Example fix
// before (i=50000000, rejected) $pbkdf2-sha256$i=50000000$... // after (i=600000, accepted) $pbkdf2-sha256$i=600000$...
Defensive patterns
Strategy: validation
Validate before calling
func pbkdf2IterationsOK(i uint32) bool { return i >= 1 && i <= 10_000_000 }
// Or pre-validate the whole hash: hash.ValidateImportedHash(hashed) Try / catch
if err := hash.ValidateImportedHash(raw); errors.Is(err, hash.ErrHashParametersOutOfBounds) {
return fmt.Errorf("pbkdf2 iterations out of range: %w", err)
} Prevention
- Follow OWASP 2023 guidance: 600k (SHA-256) / 210k (SHA-512) iterations
- Audit legacy PBKDF2 exports for FIPS-style multi-million iteration counts before import
- Use ValidateImportedHash at intake and rehash-on-login to lower iteration counts over time
When it happens
Trigger: decodePbkdf2Hash parses a PBKDF2 hash (e.g. $pbkdf2-sha256$i=... or {PBKDF2}... format) whose iteration count is 0 or exceeds 10,000,000, via ValidateImportedHash or during password comparison.
Common situations: Importing hashes from systems configured with tens of millions of iterations (e.g. long-lived high-security deployments or FIPS-style configs); hand-edited hash strings; zeroed iterations from a corrupt export.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- firescrypt ln= exceeds max
- firescrypt r= not in [1, ]
- firescrypt p= not in [1, ]
- scrypt N= not in [1, ]
- scrypt r= not in [1, ]
AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07).
Data as JSON: /api/errors/d2c62f13c9a37bbb.
Report an issue: GitHub.
Appendix: source
Thrown at hash/hash_limits.go:120
return nil
}
func validateArgon2Params(memoryKiB uint64, iterations uint32, parallelism uint8) error {
if memoryKiB == 0 || memoryKiB > uint64(maxArgon2MemoryKiB) {
return errors.Wrapf(ErrHashParametersOutOfBounds, "argon2 m=%d KiB not in [1, %d]", memoryKiB, maxArgon2MemoryKiB)
}
if iterations == 0 || iterations > maxArgon2Iterations {
return errors.Wrapf(ErrHashParametersOutOfBounds, "argon2 t=%d not in [1, %d]", iterations, maxArgon2Iterations)
}
if parallelism == 0 || parallelism > maxArgon2Parallelism {
return errors.Wrapf(ErrHashParametersOutOfBounds, "argon2 p=%d not in [1, %d]", parallelism, maxArgon2Parallelism)
}
return nil
}
func validatePbkdf2Params(iterations uint32) error {
if iterations == 0 || iterations > maxPbkdf2Iterations {
return errors.Wrapf(ErrHashParametersOutOfBounds, "pbkdf2 i=%d not in [1, %d]", iterations, maxPbkdf2Iterations)
}
return nil
}
func validateBcryptHashCost(hashed []byte) error {
cost, err := bcrypt.Cost(hashed)
if err != nil {
return err
}
if cost > maxBcryptCost {
return errors.Wrapf(ErrHashParametersOutOfBounds, "bcrypt cost=%d exceeds max %d", cost, maxBcryptCost)
}
return nil
}
// ValidateImportedHash performs cost-parameter bounds checking on a hash
// before it is persisted via the admin identity import API. It is the
// import-time counterpart to the bounds checks in the compare* paths andView on GitHub (pinned to b86338da04)