jwtk/jjwt · error · IllegalArgumentException
Values must be either String or ${type.getName()} instances.
Error message
Values must be either String or ${type.getName()} instances. Value type found: ${value.getClass().getName()}. What it means
EncodedObjectConverter.applyFrom converts a raw input value into the target encoded object type (e.g. TextCodec-decoded byte arrays). It accepts only the target type itself or a CharSequence (interpreted as its encoded String form); any other type throws IllegalArgumentException stating the accepted value types and the offending runtime type.
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/lang/EncodedObjectConverter.java:46
}
@Override
public Object applyTo(T t) {
Assert.notNull(t, "Value argument cannot be null.");
return converter.applyTo(t);
}
@Override
public T applyFrom(Object value) {
Assert.notNull(value, "Value argument cannot be null.");
if (type.isInstance(value)) {
return type.cast(value);
} else if (value instanceof CharSequence) {
return converter.applyFrom((CharSequence) value);
} else {
String msg = "Values must be either String or " + type.getName() +
" instances. Value type found: " + value.getClass().getName() + ".";
throw new IllegalArgumentException(msg);
}
}
}
View on GitHub (pinned to fb71496164)
Solutions
- Convert the value to String (or the exact target type) before passing: String.valueOf(v) or Base64 encoder.
- Ensure byte[] values are passed as byte[], and textual encodings as String - don't pass wrapper/container objects.
- Normalize JSON-parsed values: coerce Numbers/containers to the expected textual form.
Example fix
// before
byte[] key = converter.applyFrom(secretMap.get("k")); // Integer
// after
Object v = secretMap.get("k");
byte[] key = converter.applyFrom(v instanceof byte[] ? v : String.valueOf(v)); Defensive patterns
Strategy: type-guard
Validate before calling
if (!(value instanceof CharSequence) && !(value instanceof byte[])) {
value = String.valueOf(value);
} Type guard
static boolean isEncodable(Object v) {
return v instanceof CharSequence || v instanceof byte[];
} Try / catch
try {
T obj = converter.applyFrom(value);
} catch (IllegalArgumentException e) {
// convert value to String/target type and retry
} Prevention
- Pass text encodings as String and raw data as byte[] - nothing else
- Normalize JSON-parsed values (Numbers, containers) to strings first
- Keep claim schemas stable between producers and consumers
When it happens
Trigger: Passing a byte[]-incompatible object (Integer, Map, JSONObject, null-wrapped boxed types) where a String or the target encoded object is expected, e.g. setting a key/secret/IV claim with a non-String, non-byte-array value.
Common situations: Reading claim values from a JSON library that yields JSONArray/JSONObject or Numbers instead of Strings; passing Base64-decoded byte[] where a Base64 String is expected (or vice versa); wrong claim type after a schema change.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- ${message}Object of class [${objClassName}] must be an insta
- ${message}${subType} is not assignable to ${superType}
- constant [%s] does not exist in enum type %s
- Source is not an array:
- Invalid claims: + t.getMessage()
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/0a7febc9860eff36.
Report an issue: GitHub.