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

  1. Quote every element of the list so all are strings.
  2. Use the printed idx from the message to fix just the offending element.
  3. 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

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


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)