Netflix/zuul · error · TlsFatalAlert
decrypt_error
decrypt_error
Error message
Invalid or expired client PSk identity
What it means
In ZuulPskServer.getExternalPSK, when the external TLS-PSK provider throws PskCreationFailureException with the TLS alert decrypt_error, it is translated into a TlsFatalAlert(decrypt_error, 'Invalid or expired client PSk identity'). This means the client presented a known-format PSK identity but the key material could not be used: the PSK is wrong, corrupted, or has expired, so the TLS 1.3 handshake fails with a decrypt_error alert.
Solutions
- Verify the client's PSK key material matches the server's externalTlsPskProvider records
- Check PSK expiry/rotation: reissue credentials if the identity's validity window has lapsed
- Ensure clocks are synchronized if expiry is time-based
- Confirm no TLS version/cipher-suite mismatch is corrupting key derivation between client and server
Defensive patterns
Strategy: fallback
When it happens
Trigger: Thrown at zuul-core/src/main/java/com/netflix/zuul/netty/server/psk/ZuulPskServer.java:172 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of Netflix/zuul@14bf53c52d (2026-09-07).
Data as JSON: /api/errors/24371ddc501c639a.
Report an issue: GitHub.
Appendix: source
Thrown at zuul-core/src/main/java/com/netflix/zuul/netty/server/psk/ZuulPskServer.java:172
@Override
@SneakyThrows
public TlsPSKExternal getExternalPSK(Vector clientPskIdentities) {
byte[] clientPskIdentity = ((PskIdentity) clientPskIdentities.get(0)).getIdentity();
byte[] psk;
try {
this.ctx
.channel()
.attr(TlsPskHandler.CLIENT_PSK_IDENTITY_ATTRIBUTE_KEY)
.set(new ClientPSKIdentityInfo(List.copyOf(Bytes.asList(clientPskIdentity))));
psk = externalTlsPskProvider.provide(
clientPskIdentity,
this.context.getSecurityParametersHandshake().getClientRandom());
} catch (PskCreationFailureException e) {
throw switch (e.getTlsAlertMessage()) {
case unknown_psk_identity ->
new TlsFatalAlert(AlertDescription.unknown_psk_identity, "Unknown or null client PSk identity");
case decrypt_error ->
new TlsFatalAlert(AlertDescription.decrypt_error, "Invalid or expired client PSk identity");
};
}
TlsSecret pskTlsSecret = getCrypto().createSecret(psk);
int prfAlgorithm = getPRFAlgorithm13(getSelectedCipherSuite());
return new BasicTlsPSKExternal(clientPskIdentity, pskTlsSecret, prfAlgorithm);
}
@Override
public void notifyAlertRaised(short alertLevel, short alertDescription, String message, Throwable cause) {
super.notifyAlertRaised(alertLevel, alertDescription, message, cause);
Consumer<String> loggerFunc = (alertLevel == AlertLevel.fatal) ? LOGGER::error : LOGGER::debug;
loggerFunc.accept("TLS/PSK server raised alert: " + AlertLevel.getText(alertLevel) + ", "
+ AlertDescription.getText(alertDescription));
if (message != null) {
loggerFunc.accept("> " + message);
}
if (cause != null) {
LOGGER.error("TLS/PSK alert stacktrace", cause);View on GitHub (pinned to 14bf53c52d)