jwtk/jjwt · error · UnsupportedOperationException
JWKs are immutable and may not be modified.
Error message
JWKs are immutable and may not be modified.
What it means
JWK instances expose a read-only Map view over their name/value pairs. Any mutation attempt (put, remove, putAll, clear) throws UnsupportedOperationException because RFC 7517 JWKs are treated as immutable once built.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/AbstractJwk.java:245
}
@Override
public Set<String> keySet() {
return Collections.immutable(this.context.keySet());
}
@Override
public Collection<Object> values() {
return Collections.immutable(this.context.values());
}
@Override
public Set<Entry<String, Object>> entrySet() {
return Collections.immutable(this.context.entrySet());
}
private static Object immutable() {
throw new UnsupportedOperationException(IMMUTABLE_MSG);
}
@Override
public Object put(String s, Object o) {
return immutable();
}
@Override
public Object remove(Object o) {
return immutable();
}
@Override
public void putAll(Map<? extends String, ?> m) {
immutable();
}
@OverrideView on GitHub (pinned to fb71496164)
Solutions
- Set all desired fields on the JwkContext before building: Jwks.builder().put(...).build().
- Create a new JWK with the additional values instead of mutating the existing one.
- If you need a mutable copy: new HashMap<>(jwk) and mutate that.
- Never write through the entrySet() view; it is wrapped by Collections.immutable.
Example fix
// before
jwk.put("kid", "my-key-id");
// after
Jwk<?> updated = Jwks.builder().putAll(jwk).put("kid", "my-key-id").build(); Defensive patterns
Strategy: type-guard
Type guard
boolean isMutable(Map<String,Object> m) { try { m.size(); return !(m instanceof Jwk); } catch (UnsupportedOperationException e) { return false; } } Try / catch
try { map.put(k, v); }
catch (UnsupportedOperationException e) { throw new IllegalStateException("JWKs are immutable; rebuild instead", e); } Prevention
- Treat Jwk as read-only value objects.
- Configure all fields via the builder before build().
- Copy into a HashMap when mutation is needed.
- Never write through entrySet().
When it happens
Trigger: Calling jwk.put("kid", v), jwk.remove(...), jwk.putAll(...), or jwk.clear() on any Jwk instance, or mutating a collection obtained via jwk.entrySet().
Common situations: Attempting to add a 'kid' or custom claim to an already-parsed JWK; framework code that mutates maps generically; code ported from a mutable-map style.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- ${getName()} instance is immutable and may not be modified.
- Unrecognized JWA EC curve id '${jwaCurveId}'
- Unable to create ${type.getSimpleName()} from JWK ${ctx}: ${
- Unsupported JwkContext.
- A ${Key.class.getName()} or one or more name/value pairs mus
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/6e1c266dc9f4a78a.
Report an issue: GitHub.