{"record":{"id":"b9a5b076435849d8","repo":"grpc/grpc-java","slug":"value-s-for-key-s-in-s-is-not-string","errorCode":null,"errorMessage":"value '%s' for key '%s' in '%s' is not String","messagePattern":"value '(.+?)' for key '(.+?)' in '(.+?)' is not String","errorType":"validation","errorClass":"ClassCastException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/grpc/internal/JsonUtil.java","lineNumber":198,"sourceCode":"      }\n    }\n    throw new IllegalArgumentException(\n        String.format(\"value '%s' for key '%s' is not a long integer\", value, key));\n  }\n\n  /**\n   * Gets a string from an object for the given key.  If the key is not present, this returns null.\n   * If the value is not a String, throws an exception.\n   */\n  @Nullable\n  public static String getString(Map<String, ?> obj, String key) {\n    assert key != null;\n    if (!obj.containsKey(key)) {\n      return null;\n    }\n    Object value = obj.get(key);\n    if (!(value instanceof String)) {\n      throw new ClassCastException(\n          String.format(\"value '%s' for key '%s' in '%s' is not String\", value, key, obj));\n    }\n    return (String) value;\n  }\n\n  /**\n   * Gets a string from an object for the given key, parsed as a duration (defined by protobuf).  If\n   * the key is not present, this returns null.  If the value is not a String or not properly\n   * formatted, throws an exception.\n   */\n  public static Long getStringAsDuration(Map<String, ?> obj, String key) {\n    String value = getString(obj, key);\n    if (value == null) {\n      return null;\n    }\n    try {\n      return parseDuration(value);\n    } catch (ParseException e) {","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/core/src/main/java/io/grpc/internal/JsonUtil.java#L180-L216","documentation":"getString requires that a key present in the JSON object maps to a String; otherwise it throws ClassCastException naming the value, key, and whole object. gRPC uses it when parsing string config fields (e.g. LB policy names, target strings), and strict typing avoids silent coercion bugs.","triggerScenarios":"JsonUtil.getString(map, key) where the value is a number, boolean, list, or object — e.g. {\"loadBalancingPolicy\": 5} or {\"method\": {\"a\":1}}.","commonSituations":"Service config with an unquoted number or boolean where a string is expected; JSON tooling that auto-types values (dates, IDs becoming numbers); nested object pasted into a string field.","solutions":["Quote the value in the JSON so it is a string: 5 -> \"5\".","Check the third '%s' in the message to see the whole offending object and locate the mis-typed field.","Add schema validation for string fields before passing config to gRPC."],"exampleFix":"// before\n{\"loadBalancingPolicy\": 5}\n// after\n{\"loadBalancingPolicy\": \"round_robin\"}","handlingStrategy":"type-guard","validationCode":"Object v = config.get(\"loadBalancingPolicy\");\nif (v != null && !(v instanceof String)) {\n  throw new IllegalArgumentException(\"loadBalancingPolicy must be a string, got: \" + v.getClass());\n}","typeGuard":"boolean isString(Object v) { return v instanceof String; }","tryCatchPattern":"try {\n  String policy = JsonUtil.getString(config, \"loadBalancingPolicy\");\n} catch (ClassCastException e) {\n  log.error(\"String config field has wrong type: \" + e.getMessage());\n}","preventionTips":["Quote all string config values, including numeric-looking IDs.","Disable auto-typing in config generators for string fields.","Validate string fields with JSON Schema."],"tags":["grpc","json","config","type"],"backgroundTag":"type-mismatch","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}