ory/hydra · error
jwksx: "%s" does not support arbitrary key length
Error message
jwksx: "%s" does not support arbitrary key length
What it means
generate() validates the requested bit size for elliptic-curve and EdDSA algorithms (ES256/ES384/ES512/EdDSA). These algorithms have fixed key sizes (256, 384, 521, 256 bits respectively), so any non-zero bits value that differs from the fixed size is rejected with this error. Passing bits=0 uses the algorithm's default size and is allowed.
Source
Thrown at oryx/jwksx/generator.go:65
return []string{
string(jose.HS256), string(jose.HS384), string(jose.HS512),
string(jose.ES256), string(jose.ES384), string(jose.ES512), string(jose.EdDSA),
string(jose.RS256), string(jose.RS384), string(jose.RS512), string(jose.PS256), string(jose.PS384), string(jose.PS512),
}
}
// generate generates keypair for corresponding SignatureAlgorithm.
func generate(alg jose.SignatureAlgorithm, bits int) (crypto.PrivateKey, error) {
switch alg {
case jose.ES256, jose.ES384, jose.ES512, jose.EdDSA:
keylen := map[jose.SignatureAlgorithm]int{
jose.ES256: 256,
jose.ES384: 384,
jose.ES512: 521, // sic!
jose.EdDSA: 256,
}
if bits != 0 && bits != keylen[alg] {
return nil, errors.Errorf(`jwksx: "%s" does not support arbitrary key length`, alg)
}
case jose.RS256, jose.RS384, jose.RS512, jose.PS256, jose.PS384, jose.PS512:
if bits == 0 {
bits = 2048
}
if bits < 2048 {
return nil, errors.Errorf(`jwksx: key size must be at least 2048 bit for algorithm "%s"`, alg)
}
case jose.HS256:
if bits == 0 {
bits = 256
}
if bits < 256 {
return nil, errors.Errorf(`jwksx: key size must be at least 256 bit for algorithm "%s"`, alg)
}
case jose.HS384:
if bits == 0 {
bits = 384View on GitHub (pinned to 4174065ffb)
Solutions
- Pass bits=0 to use the algorithm's default key size
- Pass the exact fixed size: 256 for ES256/EdDSA, 384 for ES384, 521 (not 512) for ES512
- Switch to an RSA (RS*/PS*) or HMAC (HS*) algorithm if an arbitrary key length is genuinely required
Example fix
// before
jwks, err := jwksx.GenerateSigningKeys("kid", "ES256", 2048)
// after
jwks, err := jwksx.GenerateSigningKeys("kid", "ES256", 0) // or 256 Defensive patterns
Strategy: validation
Validate before calling
func validBitsForAlg(alg string, bits int) error {
fixed := map[string]int{"ES256": 256, "ES384": 384, "ES512": 521, "EdDSA": 256}
if want, ok := fixed[alg]; ok && bits != 0 && bits != want {
return fmt.Errorf("%s requires exactly %d bits (or 0 for default), got %d", alg, want, bits)
}
return nil
} Try / catch
jwks, err := jwksx.GenerateSigningKeys(id, alg, bits)
if err != nil {
if strings.Contains(err.Error(), "does not support arbitrary key length") {
// retry with default size
jwks, err = jwksx.GenerateSigningKeys(id, alg, 0)
}
return err
} Prevention
- Pass bits=0 for EC/EdDSA algorithms and let the library pick the size
- Remember ES512 uses 521 bits (P-521), not 512
- Do not feed RSA-style sizes (2048/4096) into EC algorithm configs
- Validate algorithm+bits pairs together in config parsing
When it happens
Trigger: Calling GenerateSigningKeys(id, alg, bits) with alg one of ES256, ES384, ES512, EdDSA and bits set to any value other than 0 or the algorithm's exact fixed size (256/384/521/256). E.g. GenerateSigningKeys(id, "ES256", 512).
Common situations: Reusing a generic key-generation helper that passes a user-supplied bits parameter (e.g. 2048 or 4096 from config) for all algorithms; assuming ES512 uses 512 bits when it actually uses 521 (P-521); copy-pasting RSA-style sizes into EC algorithm config.
Related errors
- a key ID must be specified when multiple JWK sets are config
- jwksx: key size must be at least 2048 bit for algorithm "%s"
- jwksx: key size must be at least 256 bit for algorithm "%s"
- jwksx: key size must be at least 2038448 bit for algorithm "
- jwksx: key size must be at least 512 bit for algorithm "%s"
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/0a25d42333a526df.
Report an issue: GitHub.