apache/beam · error · IllegalArgumentException

${this.getClass().getCanonicalName()} supports Integer, Long

Error message

${this.getClass().getCanonicalName()} supports Integer, Long, String and byte[] objects directly not for ${type} type, you must provide a Mapping use via.

What it means

The per-key variant of ApproximateCountDistinct validates the encoded key/value type descriptors before wiring HllCount.Init.perKey(). When the input type is not one of the directly supported types (Integer, Long, String, byte[]), it throws IllegalArgumentException naming the offending type and instructing the developer to supply a mapping via via().

Source

Thrown at sdks/java/extensions/zetasketch/src/main/java/org/apache/beam/sdk/extensions/zetasketch/ApproximateCountDistinct.java:237

        return input.apply(builder.perKey()).apply(HllCount.Extract.perKey());
      }

      // Boiler plate to avoid  [argument] NonNull vs Nullable
      Contextful<Fn<KV<K, V>, KV<K, Long>>> mapping = getMapping();

      if (mapping != null) {
        Coder<K> keyCoder = ((KvCoder<K, V>) input.getCoder()).getKeyCoder();
        return input
            .apply(
                MapElements.into(
                        TypeDescriptors.kvs(
                            keyCoder.getEncodedTypeDescriptor(), TypeDescriptors.longs()))
                    .via(mapping))
            .apply(HllCount.Init.forLongs().perKey())
            .apply(HllCount.Extract.perKey());
      }

      throw new IllegalArgumentException(
          String.format(
              "%s supports Integer,"
                  + " Long, String and byte[] objects directly not for %s type, you must provide a Mapping use via.",
              this.getClass().getCanonicalName(), type.toString()));
    }

    @Override
    public void populateDisplayData(DisplayData.Builder builder) {
      super.populateDisplayData(builder);
      ApproximateCountDistinct.populateDisplayData(builder, getPrecision());
    }
  }

  /////////////////////////////////////////////////////////////////////////////

  private static void populateDisplayData(DisplayData.Builder builder, Integer precision) {
    builder.add(DisplayData.item("precision", precision).withLabel("Precision"));
  }

View on GitHub (pinned to 12126d8942)

Solutions

  1. Supply a mapping function (e.g. via kv -> kv.getValue().toString()) to convert to a supported type.
  2. Pre-map the PCollection with MapElements into longs/strings/bytes before perKey counting.
  3. Serialize unsupported values to byte[] explicitly.
  4. Check the message's printed type to see exactly which side (key/value) is unsupported.

Example fix

// before
kvPc.apply(ApproximateCountDistinct.<String, Double>perKey());
// after
kvPc.apply(MapElements.into(TypeDescriptors.kvs(TypeDescriptors.strings(), TypeDescriptors.longs()))
    .via(kv -> KV.of(kv.getKey(), Double.doubleToLongBits(kv.getValue()))))
  .apply(ApproximateCountDistinct.perKey());
Defensive patterns

Strategy: validation

Validate before calling

if (!isHllSupported(kvType.getKeyType()) || !isHllSupported(kvType.getValueType())) {
  // supply mapping before perKey counting
}

Type guard

boolean isHllKvSupported(TypeDescriptor<KV<?, ?>> t) {
  return isHllSupported(t.getKeyType()) && isHllSupported(t.getValueType());
}

Try / catch

try {
  return kvPc.apply(ApproximateCountDistinct.perKey());
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("you must provide a Mapping")) { /* map key/value */ }
  throw e;
}

Prevention

When it happens

Trigger: Applying ApproximateCountDistinct perKey to a KV PCollection whose key or value type is not Integer/Long/String/byte[] and no mapping function was supplied.

Common situations: Counting distinct values per key where values are Doubles, POJOs, or Rows; schema-typed pipelines feeding Rows into HLL counting directly.

Related errors


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