grpc/grpc-java · error · ClassCastException
value ' ' for idx in ' ' is not string
Error message
value '%s' for idx %d in '%s' is not string
What it means
checkStringList validates that every element of a JSON list is a String and returns the list cast to List<String>. Non-string elements raise ClassCastException 'value ... is not string' with index and full list. Used via getListOfStrings for string-array config fields.
Solutions
- Quote every element of the list so all are strings.
- Use the printed idx from the message to fix just the offending element.
- Enforce array-of-string typing with JSON Schema or a builder API instead of raw JSON.
Example fix
// before
{"supportedLocales": ["en", 5, null]}
// after
{"supportedLocales": ["en", "5"]} Defensive patterns
Strategy: validation
Validate before calling
Object v = config.get("supportedLocales");
if (v instanceof List) {
for (Object e : (List<?>) v) {
if (!(e instanceof String)) {
throw new IllegalArgumentException("supportedLocales elements must be strings, got: " + e);
}
}
} Type guard
boolean isListOfStrings(Object v) {
return v instanceof List && ((List<?>) v).stream().allMatch(e -> e instanceof String);
} Try / catch
try {
List<String> l = JsonUtil.checkStringList(rawList);
} catch (ClassCastException e) {
log.error("List-of-strings config field malformed: " + e.getMessage());
} Prevention
- Quote every element in string arrays.
- Reject null/mixed-type arrays at config load.
- Prefer gRPC's typed ServiceConfig builders over raw JSON maps.
When it happens
Trigger: JsonUtil.checkStringList(rawList) — reached via getListOfStrings — where an element is a number, boolean, object, or array, e.g. {"languages": ["en", 5]} or a null element.
Common situations: Service config lists (e.g. method names, user-agent lists) containing unquoted numbers or nulls; JSON generators emitting mixed-type arrays; hand-edited configs missing quotes.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- value for idx in is not object
- value ' ' for key ' ' in ' ' is not Boolean
- value ' ' for key ' ' in ' ' is not String
- Authorization policy should be a JSON object. Found: null
- Number expected to be integer:
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/363777b6fb9d0ca1.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/io/grpc/internal/JsonUtil.java:263
for (int i = 0; i < rawList.size(); i++) {
if (!(rawList.get(i) instanceof Map)) {
throw new ClassCastException(
String.format(
Locale.US, "value %s for idx %d in %s is not object", rawList.get(i), i, rawList));
}
}
return (List<Map<String, ?>>) rawList;
}
/**
* Casts a list of unchecked JSON values to a list of String. If the given list
* contains a value that is not a String, throws an exception.
*/
@SuppressWarnings("unchecked")
public static List<String> checkStringList(List<?> rawList) {
for (int i = 0; i < rawList.size(); i++) {
if (!(rawList.get(i) instanceof String)) {
throw new ClassCastException(
String.format(
Locale.US,
"value '%s' for idx %d in '%s' is not string", rawList.get(i), i, rawList));
}
}
return (List<String>) rawList;
}
private static final long DURATION_SECONDS_MIN = -315576000000L;
private static final long DURATION_SECONDS_MAX = 315576000000L;
/**
* Parse from a string to produce a duration. Copy of
* {@link com.google.protobuf.util.Durations#parse}.
*
* @return A Duration parsed from the string.
* @throws ParseException if parsing fails.
*/View on GitHub (pinned to 64daddc1f3)