grpc/grpc-java · error · ClassCastException

value ' ' for key ' ' in ' ' is not Boolean

Error message

value '%s' for key '%s' in '%s' is not Boolean

What it means

getBoolean requires the value at the key to be a JSON Boolean; anything else raises ClassCastException 'is not Boolean'. It is used for boolean service-config flags (e.g. retry/health-check toggles), where strict typing prevents truthy-string bugs.

Solutions

  1. Use JSON true/false literals instead of "true"/"false" strings or 1/0.
  2. Coerce the value in your config loader (map "true"/"false"/1/0 to booleans) before passing to gRPC.
  3. Validate boolean fields with a schema before parsing.

Example fix

// before
{"enableRetry": "true"}
// after
{"enableRetry": true}
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = config.get("enableRetry");
if (v != null && !(v instanceof Boolean)) {
  throw new IllegalArgumentException("enableRetry must be a JSON boolean, got: " + v);
}

Type guard

boolean isBoolean(Object v) { return v instanceof Boolean; }

Try / catch

try {
  Boolean b = JsonUtil.getBoolean(config, "enableRetry");
} catch (ClassCastException e) {
  log.error("Boolean config field has wrong type: " + e.getMessage());
}

Prevention

When it happens

Trigger: JsonUtil.getBoolean(map, key) where value is a string "true"/"false", a 0/1 number, or any non-boolean type.

Common situations: Config written as {"enableRetry": "true"} (quoted) or {"enableRetry": 1}; converting YAML/env-based configs to JSON without type coercion.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/io/grpc/internal/JsonUtil.java:233

      return parseDuration(value);
    } catch (ParseException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Gets a boolean from an object for the given key.  If the key is not present, this returns null.
   * If the value is not a Boolean, throws an exception.
   */
  @Nullable
  public static Boolean getBoolean(Map<String, ?> obj, String key) {
    assert key != null;
    if (!obj.containsKey(key)) {
      return null;
    }
    Object value = obj.get(key);
    if (!(value instanceof Boolean)) {
      throw new ClassCastException(
          String.format("value '%s' for key '%s' in '%s' is not Boolean", value, key, obj));
    }
    return (Boolean) value;
  }

  /**
   * Casts a list of unchecked JSON values to a list of checked objects in Java type.
   * If the given list contains a value that is not a Map, throws an exception.
   */
  @SuppressWarnings("unchecked")
  public static List<Map<String, ?>> checkObjectList(List<?> rawList) {
    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));
      }
    }

View on GitHub (pinned to 64daddc1f3)