ory/kratos · error · ErrHashParametersOutOfBounds
firescrypt r= not in [1, ]
Error message
firescrypt r=%d not in [1, %d]
What it means
This error means a Firebase scrypt hash declares an r (block size) parameter outside the valid range [1, 8]. r=0 is invalid because the scrypt memory cost 128*N*r would be zero; r>8 exceeds the RFC 7914 standard block size and would inflate memory use beyond the package's bounds. It wraps ErrHashParametersOutOfBounds from validateFirebaseScryptParams during hash decode.
Solutions
- Inspect the r field in the hash string and ensure it is an integer in [1, 8] (Firebase uses r=8)
- Regenerate or re-export the hash with the standard r=8
- If the hash is corrupted, re-hash the password from its source rather than repairing the string by hand
Example fix
// before (r=0, invalid) $firescrypt$ln=14$r=0$p=1$... // after (r=8, valid) $firescrypt$ln=14$r=8$p=1$...
Defensive patterns
Strategy: validation
Validate before calling
func firebaseScryptROK(r uint32) bool { return r >= 1 && r <= 8 }
// Or pre-validate the whole hash: hash.ValidateImportedHash(hashed) Try / catch
if err := hash.ValidateImportedHash(raw); errors.Is(err, hash.ErrHashParametersOutOfBounds) {
return fmt.Errorf("invalid firescrypt r: %w", err)
} Prevention
- Always export Firebase hashes with r=8 (Firebase's standard block size)
- Never hand-construct hash strings for seeding; use the exporter tooling
- Validate hashes at import time with ValidateImportedHash
When it happens
Trigger: decodeFirebaseScryptHash encounters a $firescrypt hash string with r=0 or r>8 in its parameters, either via ValidateImportedHash on import or during password comparison.
Common situations: Malformed or hand-crafted hash strings with missing/zero parameters; hashes exported from tools using non-standard scrypt block sizes; typo when manually constructing a hash for seeding test users.
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 p= not in [1, ]
- scrypt N= not in [1, ]
- scrypt r= not in [1, ]
- scrypt p= not in [1, ]
AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07).
Data as JSON: /api/errors/c1eb5e05e337835e.
Report an issue: GitHub.
Appendix: source
Thrown at hash/hash_limits.go:84
// maxPbkdf2Iterations bounds PBKDF2 i. OWASP 2023 recommends 600k
// (SHA-256) / 210k (SHA-512). 10M ≈ 10× the strongest published
// recommendation and bounds CPU to a few seconds on modern hardware.
maxPbkdf2Iterations uint32 = 10_000_000
// maxBcryptCost bounds bcrypt cost. The format spec allows 4–31, but
// cost grows exponentially: cost 12 (Kratos, PHP, Django default) is
// ~250 ms; cost 14 (high-security guidance) is ~1 s; cost 15 (practical
// max for interactive use) is ~2 s; cost 17 is ~8 s. No mainstream
// platform defaults above cost 12.
maxBcryptCost = 15
)
func validateFirebaseScryptParams(logN, r, p uint32) error {
if logN > maxScryptLogN {
return errors.Wrapf(ErrHashParametersOutOfBounds, "firescrypt ln=%d exceeds max %d", logN, maxScryptLogN)
}
if r == 0 || r > maxScryptR {
return errors.Wrapf(ErrHashParametersOutOfBounds, "firescrypt r=%d not in [1, %d]", r, maxScryptR)
}
if p == 0 || p > maxScryptP {
return errors.Wrapf(ErrHashParametersOutOfBounds, "firescrypt p=%d not in [1, %d]", p, maxScryptP)
}
return nil
}
func validateScryptParams(n, r, p uint32) error {
if n == 0 || n > maxScryptN {
return errors.Wrapf(ErrHashParametersOutOfBounds, "scrypt N=%d not in [1, %d]", n, maxScryptN)
}
if r == 0 || r > maxScryptR {
return errors.Wrapf(ErrHashParametersOutOfBounds, "scrypt r=%d not in [1, %d]", r, maxScryptR)
}
if p == 0 || p > maxScryptP {
return errors.Wrapf(ErrHashParametersOutOfBounds, "scrypt p=%d not in [1, %d]", p, maxScryptP)
}
return nilView on GitHub (pinned to b86338da04)