grpc/grpc-java · error · IllegalArgumentException

The entry ' ' is of type ' ', which is not supported

Error message

The entry '${value}' is of type '${value.getClass()}', which is not supported

What it means

The list-parsing counterpart of the map check: elements of config lists are normalized to String, Double, or Boolean, and any other element type causes this IllegalArgumentException reporting the element and its class. It guards the internal channel builder against unsupported config shapes.

Solutions

  1. Replace nested entries with supported scalar types (String, Number, Boolean).
  2. Convert parsed JSON/YAML trees into flat scalar lists before passing them in.
  3. Inspect the reported value/class and coerce accordingly (e.g. ((Number) v).doubleValue()).

Example fix

// before
List<Object> cfg = Arrays.asList("a", Collections.singletonMap("k", 1));
// after
List<Object> cfg = Arrays.asList("a", "k=1");
Defensive patterns

Strategy: validation

Validate before calling

static void checkListEntries(List<Object> cfg) {
  for (Object v : cfg) {
    if (!(v instanceof String || v instanceof Number || v instanceof Boolean)) {
      throw new IllegalArgumentException("list entry '" + v + "' of type " + v.getClass() + " unsupported");
    }
  }
}

Type guard

boolean isScalarEntry(Object v) {
  return v instanceof String || v instanceof Number || v instanceof Boolean;
}

Try / catch

try {
  applyConfig(list);
} catch (IllegalArgumentException e) {
  if (e.getMessage() != null && e.getMessage().contains("which is not supported")) {
    log.error("Unsupported config list entry: {}", e.getMessage());
  } else throw e;
}

Prevention

When it happens

Trigger: Supplying a config/option List containing nested Lists, Maps, or arbitrary objects where only scalar String/Number/Boolean entries are accepted.

Common situations: Programmatically built method-config lists with nested objects; YAML/JSON parse trees (Map/List nodes) passed through unconverted instead of scalars.

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/7f4755d6f693679b. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java:656

  }

  private static List<?> checkListEntryTypes(List<?> list) {
    List<Object> parsedList = new ArrayList<>(list.size());
    for (Object value : list) {
      if (value == null) {
        parsedList.add(null);
      } else if (value instanceof Map) {
        parsedList.add(checkMapEntryTypes((Map<?, ?>) value));
      } else if (value instanceof List) {
        parsedList.add(checkListEntryTypes((List<?>) value));
      } else if (value instanceof String) {
        parsedList.add(value);
      } else if (value instanceof Number) {
        parsedList.add(((Number) value).doubleValue());
      } else if (value instanceof Boolean) {
        parsedList.add(value);
      } else {
        throw new IllegalArgumentException(
            "The entry '" + value + "' is of type '" + value.getClass()
                + "', which is not supported");
      }
    }
    return Collections.unmodifiableList(parsedList);
  }

  @Override
  public <X> ManagedChannelImplBuilder setNameResolverArg(NameResolver.Args.Key<X> key, X value) {
    if (nameResolverCustomArgs == null) {
      nameResolverCustomArgs = new IdentityHashMap<>();
    }
    nameResolverCustomArgs.put(checkNotNull(key, "key"), checkNotNull(value, "value"));
    return this;
  }

  @SuppressWarnings("unchecked") // This cast is safe because of setNameResolverArg()'s signature.
  void copyAllNameResolverCustomArgsTo(NameResolver.Args.Builder dest) {

View on GitHub (pinned to 64daddc1f3)