jwtk/jjwt · error · InvalidKeyException

Missing required encoded bytes for key [${toString(key)}].

Error message

Missing required encoded bytes for key [${toString(key)}].

What it means

KeysBridge.getEncoded throws InvalidKeyException with this message when key.getEncoded() succeeds but returns null or an empty array. jjwt needs actual key bytes for normalization/signing; a key with no encoded form (or one whose encoding the provider withholds) cannot be used.

Source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/KeysBridge.java:155

            if (curve != null) bitlen = curve.getKeyBitLength();
        }

        return bitlen;
    }

    public static byte[] getEncoded(Key key) {
        Assert.notNull(key, "Key cannot be null.");
        byte[] encoded;
        try {
            encoded = key.getEncoded();
        } catch (Throwable t) {
            String msg = "Cannot obtain required encoded bytes from key [" + KeysBridge.toString(key) + "]: " +
                    t.getMessage();
            throw new InvalidKeyException(msg, t);
        }
        if (Bytes.isEmpty(encoded)) {
            String msg = "Missing required encoded bytes for key [" + toString(key) + "].";
            throw new InvalidKeyException(msg);
        }
        return encoded;
    }

    public static String toString(Key key) {
        if (key == null) {
            return "null";
        }
        if (key instanceof PublicKey) {
            return key.toString(); // safe to show internal key state as it's a public key
        }
        // else secret or private key, don't show internal key state, just public attributes
        return "class: " + key.getClass().getName() +
                ", algorithm: " + key.getAlgorithm() +
                ", format: " + key.getFormat();
    }
}

View on GitHub (pinned to fb71496164)

Solutions

  1. Use a key that exposes its encoding: generate with KeyGenerator/SecretKeySpec, or keep the original bytes you constructed the key from.
  2. On Android, store raw key material outside Keystore for jjwt use, or derive a software key.
  3. For custom Key implementations, implement getEncoded() to return real bytes.
  4. If the bytes came from a keystore, reload via the original SecretKeySpec/KeyFactory rather than relying on getEncoded().

Example fix

// before
SecretKey key = keystoreSecretKeyWithNullEncoding();
Jwts.parser().verifyWith(key); // InvalidKeyException: missing encoded bytes

// after
SecretKey key = new SecretKeySpec(rawBytes, "HmacSHA256");
Jwts.parser().verifyWith(key); // has encoded bytes
Defensive patterns

Strategy: validation

Validate before calling

boolean hasEncodedForm(Key key) {
    try { byte[] enc = key.getEncoded(); return enc != null && enc.length > 0; }
    catch (Throwable t) { return false; }
}

Try / catch

try {
    parser.verifyWith(key);
} catch (InvalidKeyException e) {
    if (e.getMessage().startsWith("Missing required encoded bytes")) {
        // reconstruct with new SecretKeySpec(originalBytes, alg)
    } else throw e;
}

Prevention

When it happens

Trigger: Calling jjwt APIs that require encoded key bytes with a key whose getEncoded() returns null/empty — e.g. platform keys that deliberately expose no encoding (some Android Keystore, PKCS11 tokens returning null), or a custom Key implementation returning null.

Common situations: Android Keystore secret keys in newer API levels returning null from getEncoded(); custom Key wrappers in tests; keys reconstructed without their encoding (e.g. RSAPrivateKeySpec variants lacking CRT data normalized away).

Related errors


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