ory/kratos · error · ErrHashParametersOutOfBounds
bcrypt cost= exceeds max
Error message
bcrypt cost=%d exceeds max %d
What it means
validateBcryptHashCost parsed the cost parameter embedded in an existing bcrypt hash (during comparison or import validation) and found it above the compiled-in maxBcryptCost limit. The wrapped sentinel ErrHashParametersOutOfBounds marks this as an out-of-bounds hashing parameter; the fault is in the stored/imported hash, not in user input.
Solutions
- Regenerate the offending hash with a cost within the allowed maximum
- If the high cost is intentional and policy allows, raise maxBcryptCost and rebuild
- Reject or skip the imported credential hash that carries the excessive cost
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at hash/hash_limits.go:131 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07).
Data as JSON: /api/errors/e9a5373828e73a7d.
Report an issue: GitHub.
Appendix: source
Thrown at hash/hash_limits.go:131
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 and
// exists so we fail fast on malicious imports rather than persisting a hash
// that would crash the process at every login attempt.
//
// Hashers without attacker-controlled cost parameters (md5-crypt, sha-crypt,
// the static SHA/MD5/HMAC families, SSHA) pass through unchanged.
func ValidateImportedHash(hashed []byte) error {
switch {
case IsBcryptHash(hashed):
return validateBcryptHashCost(hashed)
case IsArgon2idHash(hashed), IsArgon2iHash(hashed):
_, _, _, err := decodeArgon2idHash(string(hashed))View on GitHub (pinned to b86338da04)