jwtk/jjwt · error

wrap(nsa, jcaName, specifiedProvider, null)

Error message

wrap(nsa, jcaName, specifiedProvider, null)

What it means

JcaTemplate.get rethrows a NoSuchAlgorithmException (via wrap) after also attempting its fallback algorithm, when a JCA service cannot be found for the requested transformation/jcaName and provider. wrap converts it into a KeystoreException/SecurityException-style runtime error naming the algorithm and provider. It signals that the JVM (or the explicitly specified provider) offers no implementation of the required cryptographic service.

Solutions

  1. Ensure the JRE supports the algorithm; install/register an appropriate JCA provider (e.g. BouncyCastle) and optionally specify it.
  2. Do not pass a restricted 'specifiedProvider' that lacks the algorithm, or use the default provider search.
  3. Check jjwt version — newer jjwt versions map algorithms to modern JCA names; upgrade if the JCA name changed.
  4. Read the wrapped exception message to confirm the exact missing algorithm and add a provider for it.

Example fix

// before
Provider p = Security.getProvider("SunJCE"); // lacks some algos
Mac mac = Jwts.SIG.HS256.mac.get(); // may wrap NoSuchAlgorithmException
// after
Security.addProvider(new BouncyCastleProvider());
Mac mac = Jwts.SIG.HS256.mac.get(); // fallback provider search succeeds
Defensive patterns

Strategy: fallback

Validate before calling

try {
    javax.crypto.Mac.getInstance("HmacSHA256");
} catch (NoSuchAlgorithmException e) {
    Security.addProvider(new BouncyCastleProvider());
}

Try / catch

try {
    Jwts.parser().verifyWith(key).build().parseSignedClaims(token);
} catch (JwtException e) {
    log.error("JCA algorithm unavailable: {}", e.getMessage(), e.getCause());
    throw new CryptoUnavailableException(e);
}

Prevention

When it happens

Trigger: Mac.getInstance / Cipher.getInstance / KeyPairGenerator.getInstance etc. for an algorithm like PBKDF2WithHmacSHA256, A128KW, or RS256's JCA name when the JRE or the provider passed in does not implement it, and the built-in fallback algorithm also fails.

Common situations: Running on FIPS-restricted JVMs, older JREs without newer algorithms (e.g. Ed25519 pre-JDK 15), IBM/SAP JDKs with different algorithm names, or specifying a Provider that does not offer the algorithm.

Related errors


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

Appendix: source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/JcaTemplate.java:402

                if (specifiedProvider == null && attempted == null) { // default provider doesn't support the alg name,
                    // and we haven't tried BC yet, so try that now:
                    Provider fallback = findBouncyCastle();
                    if (fallback != null) { // BC found, try again:
                        try {
                            T value = doGet(jcaName, fallback);
                            // record the successful attempt so we don't have to do this again:
                            FALLBACK_ATTEMPTS.putIfAbsent(jcaName, Boolean.TRUE);
                            return value;
                        } catch (Throwable ignored) {
                            // record the failed attempt so we don't keep trying and propagate original exception:
                            FALLBACK_ATTEMPTS.putIfAbsent(jcaName, Boolean.FALSE);
                        }
                    }
                }
                // otherwise, we tried the fallback, or there isn't a fallback, so no need to try again, so
                // propagate the exception:
                throw wrap(nsa, jcaName, specifiedProvider, null);
            } catch (Exception e) {
                throw wrap(e, jcaName, specifiedProvider, null);
            }
        }

        protected abstract T doGet(String jcaName, Provider provider) throws Exception;

        // visible for testing:
        protected Exception wrap(Exception e, String jcaName, Provider specifiedProvider, Provider fallbackProvider) {
            String msg = "Unable to obtain '" + jcaName + "' " + getId() + " instance from ";
            if (specifiedProvider != null) {
                msg += "specified '" + specifiedProvider + "' Provider";
            } else {
                msg += "default JCA Provider";
            }
            if (fallbackProvider != null) {
                msg += " or fallback '" + fallbackProvider + "' Provider";
            }

View on GitHub (pinned to fb71496164)