jwtk/jjwt · error · MalformedKeyException

RSA JWK 'oth' (Other Prime Info) element map cannot be empty

Error message

RSA JWK 'oth' (Other Prime Info) element map cannot be empty.

What it means

Thrown as MalformedKeyException when an element of the RSA JWK 'oth' (Other Prime Info) array is a Map but has no entries. RFC 7518 requires each 'oth' entry to carry r (prime factor), t (factor CRT exponent), and d (CRT coefficient); an empty object supplies none of them.

Source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/RSAOtherPrimeInfoConverter.java:62

        m.put(PRIME_FACTOR.getId(), PRIME_FACTOR.applyTo(info.getPrime()));
        m.put(FACTOR_CRT_EXPONENT.getId(), FACTOR_CRT_EXPONENT.applyTo(info.getExponent()));
        m.put(FACTOR_CRT_COEFFICIENT.getId(), FACTOR_CRT_COEFFICIENT.applyTo(info.getCrtCoefficient()));
        return m;
    }

    @Override
    public RSAOtherPrimeInfo applyFrom(Object o) {
        if (o == null) {
            throw new MalformedKeyException("RSA JWK 'oth' (Other Prime Info) element cannot be null.");
        }
        if (!(o instanceof Map)) {
            String msg = "RSA JWK 'oth' (Other Prime Info) must contain map elements of name/value pairs. " +
                    "Element type found: " + o.getClass().getName();
            throw new MalformedKeyException(msg);
        }
        Map<?, ?> m = (Map<?, ?>) o;
        if (Collections.isEmpty(m)) {
            throw new MalformedKeyException("RSA JWK 'oth' (Other Prime Info) element map cannot be empty.");
        }

        // Need a Context instance to satisfy the API contract of the reader.get* methods below.
        JwkContext<?> ctx = new DefaultJwkContext<>(PARAMS);
        try {
            for (Map.Entry<?, ?> entry : m.entrySet()) {
                String name = String.valueOf(entry.getKey());
                ctx.put(name, entry.getValue());
            }
        } catch (Exception e) {
            throw new MalformedKeyException(e.getMessage(), e);
        }

        ParameterReadable reader = new RequiredParameterReader(ctx);
        BigInteger prime = reader.get(PRIME_FACTOR);
        BigInteger primeExponent = reader.get(FACTOR_CRT_EXPONENT);
        BigInteger crtCoefficient = reader.get(FACTOR_CRT_COEFFICIENT);

View on GitHub (pinned to fb71496164)

Solutions

  1. Populate the 'oth' element with the required r, t, and d parameters.
  2. Remove empty objects from the 'oth' array, or remove the 'oth' member if not needed.
  3. Re-export the multi-prime RSA key from its original source with all CRT parameters.

Example fix

// before
"oth": [{}]
// after
"oth": [ {"r":"...","t":"...","d":"..."} ]
Defensive patterns

Strategy: validation

Validate before calling

boolean othNonEmpty = oth != null && oth.stream().allMatch(e -> e instanceof Map && !((Map<?,?>) e).isEmpty());

Type guard

boolean hasRequiredOthParams(Object o) { return o instanceof Map && ((Map<?,?>) o).keySet().containsAll(java.util.Arrays.asList("r","t","d")); }

Try / catch

try { /* parse JWK */ } catch (MalformedKeyException e) { throw new IllegalStateException("'oth' entry missing r/t/d parameters", e); }

Prevention

When it happens

Trigger: Parsing a JWK where 'oth' contains an empty JSON object, e.g. oth: [{}], through JWK parsing/JwkBuilder APIs.

Common situations: Template JWKs with placeholder empty objects; code that strips JWK fields (e.g. removing r/t/d individually) leaving empty maps; incomplete multi-prime key exports.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09). Data as JSON: /api/errors/36599e9705db4963. Report an issue: GitHub.