jwtk/jjwt · error · io.jsonwebtoken.security.InvalidKeyException
Either a Key instance or a kty value is required to create a
Error message
Either a Key instance or a kty value is required to create a JWK.
What it means
DispatchingJwkFactory.assertKeyOrKeyType enforces that to create a JWK you must supply either a java.security.Key instance or a kty (key type) value in the JwkContext. With neither, there is no way to select a family-specific JwkFactory, so it throws InvalidKeyException.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/DispatchingJwkFactory.java:77
@Override
public JwkContext<Key> newContext(JwkContext<?> src, Key key) {
Assert.notNull(src, "JwkContext cannot be null.");
String kty = src.getType();
assertKeyOrKeyType(key, kty);
for (FamilyJwkFactory<Key, ?> factory : this.factories) {
if (factory.supports(key) || factory.supports(src)) {
JwkContext<Key> ctx = factory.newContext(src, key);
return Assert.notNull(ctx, "FamilyJwkFactory implementation cannot return null JwkContexts.");
}
}
throw noFamily(key, kty);
}
private static void assertKeyOrKeyType(Key key, String kty) {
if (key == null && !Strings.hasText(kty)) {
String msg = "Either a Key instance or a " + AbstractJwk.KTY + " value is required to create a JWK.";
throw new InvalidKeyException(msg);
}
}
@Override
public Jwk<Key> createJwk(JwkContext<Key> ctx) {
Assert.notNull(ctx, "JwkContext cannot be null.");
final Key key = ctx.getKey();
final String kty = Strings.clean(ctx.getType());
assertKeyOrKeyType(key, kty);
for (FamilyJwkFactory<Key, ?> factory : this.factories) {
if (factory.supports(ctx)) {
String algFamilyId = Assert.hasText(factory.getId(), "factory id cannot be null or empty.");
if (kty == null) {
ctx.setType(algFamilyId); //ensure the kty is available for the rest of the creation process
}View on GitHub (pinned to fb71496164)
Solutions
- Set a Key on the builder: Jwks.builder().setKey(key).build().
- Or set the key type explicitly: Jwks.builder().setKty("RSA").put(...).build().
- Ensure context values are populated before calling createJwk when building contexts manually.
Example fix
// before
Jwk jwk = Jwks.builder().put("n", n).put("e", e).build();
// after
Jwk jwk = Jwks.builder().setKty("RSA").put("n", n).put("e", e).build(); Defensive patterns
Strategy: validation
Validate before calling
if (key == null && (kty == null || kty.trim().isEmpty())) {
throw new IllegalArgumentException("Provide either a Key or a kty value to build a JWK");
} Try / catch
try {
Jwk<?> jwk = Jwks.builder().setKey(key).build();
} catch (io.jsonwebtoken.security.InvalidKeyException e) {
// set kty or key before building
} Prevention
- Always call setKey(...) or setKty(...) on Jwks.builder()
- When building contexts dynamically, assert required fields are populated before createJwk
When it happens
Trigger: Calling Jwks.builder() without .setKey(...) and without .setKty(...); building a JwkContext programmatically with an empty context and calling createJwk.
Common situations: Fluent Jwks.builder() chains where the developer forgot to set the key or kty; dynamic JWK creation where values are conditionally populated and both key and kty end up absent.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Unrelated key operations are not allowed. KeyOperation [${in
- Unable to derive ECPublicKey from ECPrivateKey: ${e.getMessa
- The specified ECKey curve does not match a JWA standard curv
- ECPublicKey's ECPoint does not exist on elliptic curve '%s'
- EC JWK x,y coordinates do not exist on elliptic curve '%s'.
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/7e18f29629d8265e.
Report an issue: GitHub.