ory/kratos · error · ErrHashParametersOutOfBounds

argon2 p= not in [1, ]

Error message

argon2 p=%d not in [1, %d]

What it means

This error means an Argon2 hash declares a parallelism (p/lanes) parameter that is 0 or greater than 16. p=0 is invalid; the 16 ceiling covers up to 8-core hosts (default is 2*NumCPU) and bounds memory*lanes allocation per comparison. It wraps ErrHashParametersOutOfBounds from validateArgon2Params.

Solutions

  1. Check the p= field; it must be in [1, 16]
  2. Regenerate the hash with p matched to the target host (e.g. p=4)
  3. If hashes came from a high-core-count system, use rehash-on-login to bring parameters down gradually

Example fix

// before (p=64, rejected)
$argon2id$v=19$m=131072,t=3,p=64$...
// after (p=4, accepted)
$argon2id$v=19$m=131072,t=3,p=4$...
Defensive patterns

Strategy: validation

Validate before calling

func argon2ParallelismOK(p uint8) bool { return p >= 1 && p <= 16 }
// Or pre-validate the whole hash: hash.ValidateImportedHash(hashed)

Try / catch

if err := hash.ValidateImportedHash(raw); errors.Is(err, hash.ErrHashParametersOutOfBounds) {
    return fmt.Errorf("argon2 p out of range: %w", err)
}

Prevention

When it happens

Trigger: decodeArgon2idHash parses an $argon2id$ hash whose p= parameter is 0 or >16, during import validation or password comparison.

Common situations: Hashes generated on very large machines (e.g. p=64 on a 32-core server) being imported to smaller deployments; forged imports; corrupted hash strings.

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


AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07). Data as JSON: /api/errors/2a1bdaf4a5e1f6e7. Report an issue: GitHub.

Appendix: source

Thrown at hash/hash_limits.go:113

	}
	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 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)

View on GitHub (pinned to b86338da04)