apache/beam · error · CannotProvideCoderException

Cannot provide a coder for wildcard type %s.

Error message

Cannot provide a coder for wildcard type %s.

What it means

Java wildcard types (e.g. List<?>) carry no concrete element type, so the registry cannot determine or verify a coder for them. getCoderFromTypeDescriptor throws CannotProvideCoderException with ReasonCode.UNKNOWN for any WildcardType. The library deliberately refuses to guess a coder for an unknown generic type.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/coders/CoderRegistry.java:635

        coder = Iterables.getOnlyElement(coders);
      } else {
        throw new CannotProvideCoderException(
            String.format(
                "Cannot provide a coder for type variable %s"
                    + " because the actual type is over specified by multiple"
                    + " incompatible coders %s.",
                type, coders),
            ReasonCode.OVER_SPECIFIED);
      }
    } else if (type instanceof Class<?>) {
      coder = getCoderFromFactories(typeDescriptor, Collections.emptyList());
    } else if (type instanceof ParameterizedType) {
      coder = getCoderFromParameterizedType((ParameterizedType) type, typeCoderBindings);
    } else if (type instanceof TypeVariable) {
      coder = getCoderFromFactories(typeDescriptor, Collections.emptyList());
    } else if (type instanceof WildcardType) {
      // No coder for an unknown generic type.
      throw new CannotProvideCoderException(
          String.format("Cannot provide a coder for wildcard type %s.", type), ReasonCode.UNKNOWN);
    } else {
      throw new RuntimeException("Internal error: unexpected kind of Type: " + type);
    }

    LOG.debug("Coder for {}: {}", typeDescriptor, coder);
    @SuppressWarnings("unchecked")
    Coder<T> result = (Coder<T>) coder;
    return result;
  }

  /**
   * Returns a {@link Coder} to use for values of the given parameterized type, in a context where
   * the given types use the given {@link Coder Coders}.
   *
   * @throws CannotProvideCoderException if no coder can be provided
   */
  private Coder<?> getCoderFromParameterizedType(

View on GitHub (pinned to 12126d8942)

Solutions

  1. Replace the wildcard with a concrete type in the TypeDescriptor (e.g. List<String> instead of List<?>).
  2. Add an upper bound (List<? extends Foo>) and register a coder for Foo, then request the coder for the bounded type.
  3. Have the API surface use concrete generic parameters instead of wildcards.

Example fix

// before
Coder<List<?>> coder = registry.getCoder(new TypeDescriptor<List<?>>() {});
// after
Coder<List<String>> coder = registry.getCoder(new TypeDescriptor<List<String>>() {});
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeDescriptor.getType() instanceof WildcardType) {
  throw new IllegalArgumentException("Provide a concrete type instead of a wildcard");
}

Type guard

static boolean isWildcard(TypeDescriptor<?> td) {
  return td.getType() instanceof WildcardType;
}

Try / catch

try {
  coder = registry.getCoder(td);
} catch (CannotProvideCoderException e) {
  // wildcard: request coder for concrete bounded type instead
}

Prevention

When it happens

Trigger: Requesting a coder for a TypeDescriptor whose underlying Type is a WildcardType — e.g. CoderRegistry.getCoder(new TypeDescriptor<List<?>>() {}) or a parameterized type argument that resolves to a wildcard.

Common situations: Generic APIs typed with wildcards (PCollection<List<?>>); reflection-derived Type objects from frameworks that produce wildcards; incomplete type tokens using ? instead of concrete classes.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/1777b569e84ab7e6. Report an issue: GitHub.