grpc/grpc-java · error · ClassCastException

wrong type

Error message

wrong type 

What it means

DnsNameResolver parses gRPC service-config choices from DNS TXT records: each `grpc_config=` TXT record must be JSON whose top level is a list. If the parsed JSON is not a List (e.g. an object or scalar), parseTxtResults throws ClassCastException("wrong type ...") because the record cannot be interpreted as a list of service-config choices.

Solutions

  1. Fix the DNS TXT record so the value after the `grpc_config=` prefix is a JSON array of service-config choice objects.
  2. Validate each TXT record with a JSON linter (top level must be `[...]`) before publishing it.
  3. If multiple TXT records exist, remove the malformed one or set it to a non-`grpc_config` prefix so it is ignored.

Example fix

// before (TXT record)
grpc_config={"serviceConfig":{...}}
// after (TXT record)
grpc_config=[{"serviceConfig":{...}}]
Defensive patterns

Strategy: validation

Validate before calling

Object parsed = JsonParser.parse(txtRecord.substring(prefix.length()));
if (!(parsed instanceof List)) throw new IllegalArgumentException("grpc_config TXT must be a JSON array");

Type guard

boolean isJsonArray(Object o) { return o instanceof List; }

Try / catch

try {
  resolver.resolve(target);
} catch (ClassCastException e) {
  // fall back to default service config / retry resolution
}

Prevention

When it happens

Trigger: A DNS TXT record starting with the gRPC service-config prefix whose JSON value is not an array, e.g. `grpc_config={...}` (object) or `grpc_config=3`, encountered during resolution of the hostname.

Common situations: Misconfigured DNS records published by infrastructure teams; hand-edited TXT entries; service meshes emitting the wrong service-config schema; stale records left over from a config format change.

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/178ffb96ed687614. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/io/grpc/internal/DnsNameResolver.java:406

    return port;
  }

  /**
   * Parse TXT service config records as JSON.
   *
   * @throws IOException if one of the txt records contains improperly formatted JSON.
   */
  @VisibleForTesting
  static List<Map<String, ?>> parseTxtResults(List<String> txtRecords) throws IOException {
    List<Map<String, ?>> possibleServiceConfigChoices = new ArrayList<>();
    for (String txtRecord : txtRecords) {
      if (!txtRecord.startsWith(SERVICE_CONFIG_PREFIX)) {
        logger.log(Level.FINE, "Ignoring non service config {0}", new Object[]{txtRecord});
        continue;
      }
      Object rawChoices = JsonParser.parse(txtRecord.substring(SERVICE_CONFIG_PREFIX.length()));
      if (!(rawChoices instanceof List)) {
        throw new ClassCastException("wrong type " + rawChoices);
      }
      List<?> listChoices = (List<?>) rawChoices;
      possibleServiceConfigChoices.addAll(JsonUtil.checkObjectList(listChoices));
    }
    return possibleServiceConfigChoices;
  }

  @Nullable
  private static final Double getPercentageFromChoice(Map<String, ?> serviceConfigChoice) {
    return JsonUtil.getNumberAsDouble(serviceConfigChoice, SERVICE_CONFIG_CHOICE_PERCENTAGE_KEY);
  }

  @Nullable
  private static final List<String> getClientLanguagesFromChoice(
      Map<String, ?> serviceConfigChoice) {
    return JsonUtil.getListOfStrings(
        serviceConfigChoice, SERVICE_CONFIG_CHOICE_CLIENT_LANGUAGE_KEY);
  }

View on GitHub (pinned to 64daddc1f3)