jwtk/jjwt · error · java.lang.IllegalStateException
Both 'zip()' and 'compressionCodecResolver' cannot be config
Error message
Both 'zip()' and 'compressionCodecResolver' cannot be configured. Choose either.
What it means
JwtParser.build() forbids configuring both the zip(...) algorithm set and a custom compressionCodecResolver, since they are two competing ways to decide how compressed JWT payloads are decompressed. The builder throws IllegalStateException to resolve the ambiguity up front rather than during parsing.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParserBuilder.java:403
throw new IllegalStateException(msg);
}
}
Locator<? extends Key> keyLocator = this.keyLocator; // user configured default, don't overwrite to ensure further build() calls work as expected
if (keyLocator == null) {
keyLocator = new ConstantKeyLocator(this.signatureVerificationKey, this.decryptionKey);
}
if (!unsecured && unsecuredDecompression) {
String msg = "'unsecuredDecompression' is only relevant if 'unsecured' is also " +
"configured. Please read the JavaDoc of both features before enabling either " +
"due to their security implications.";
throw new IllegalStateException(msg);
}
if (this.compressionCodecResolver != null && !Jwts.ZIP.get().equals(this.zipAlgs)) {
String msg = "Both 'zip()' and 'compressionCodecResolver' " +
"cannot be configured. Choose either.";
throw new IllegalStateException(msg);
}
// Invariants. If these are ever violated, it's an error in this class implementation:
Assert.stateNotNull(keyLocator, "Key locator should never be null.");
final DefaultClaims expClaims = (DefaultClaims) this.expectedClaims.build();
return new DefaultJwtParser(
provider,
signingKeyResolver,
unsecured,
unsecuredDecompression,
keyLocator,
clock,
critical,
allowedClockSkewMillis,
expClaims,
decoder,View on GitHub (pinned to fb71496164)
Solutions
- Remove compressionCodecResolver(...) and keep zip(...) for standard algorithm selection
- Remove zip(...) and keep compressionCodecResolver(...) for fully custom resolution
- Audit the builder construction path so only one compression configuration mechanism is used
Example fix
// before
JwtParser parser = Jwts.parser()
.zip(Jwts.ZIP.DEF) // plus leftover:
.compressionCodecResolver(resolver)
.build();
// after
JwtParser parser = Jwts.parser()
.zip(Jwts.ZIP.DEF)
.build(); Defensive patterns
Strategy: validation
Validate before calling
if (codecResolver != null && zipAlgs != null) {
throw new IllegalArgumentException("Use either zip() or compressionCodecResolver, not both");
} Try / catch
try {
JwtParser p = builder.build();
} catch (IllegalStateException e) {
log.error("Compression config conflict: {}", e.getMessage());
} Prevention
- Use zip() for standard algorithms and only drop to a custom resolver when truly needed
- Strip old resolver configuration when adopting the zip() API
- Add a parser-builder unit test asserting build() succeeds
When it happens
Trigger: Calling JwtParserBuilder.zip(algorithms) and compressionCodecResolver(resolver) on the same builder, then build().
Common situations: Adding a custom codec resolver for a non-standard compression algorithm while a zip(...) whitelist from earlier code remains; wrapping legacy builder code where the newer zip() API was layered over an old resolver.
Related errors
- Both 'keyLocator' and a 'verifyWith' key cannot be configure
- 'unsecuredDecompression' is only relevant if 'unsecured' is
- Unsupported ${id} ${algType} algorithm... is disabled (no ${
- Unexpected unsecured Claims JWT.
- Unexpected content JWS.
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/db8f49655c338b6f.
Report an issue: GitHub.