apache/beam · error · IllegalArgumentException

PCollection does not use a KvCoder

Error message

PCollection does not use a KvCoder

What it means

When inferring the key coder from an input PCollection, the tuple requires the PCollection's coder to be a KvCoder so it can extract coder.getKeyCoder(). A non-KvCoder coder means the input isn't a properly-coded KV PCollection.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/join/KeyedPCollectionTuple.java:163

  /** Returns the {@link CoGbkResultSchema} associated with this {@link KeyedPCollectionTuple}. */
  public CoGbkResultSchema getCoGbkResultSchema() {
    return schema;
  }

  @Override
  public Pipeline getPipeline() {
    return pipeline;
  }

  private static <K, V> Coder<K> getKeyCoder(PCollection<KV<K, V>> pc) {
    // TODO: This should already have run coder inference for output, but may not have been consumed
    // as input yet (and won't be fully specified); This is fine

    // Assumes that the PCollection uses a KvCoder.
    Coder<?> entryCoder = pc.getCoder();
    if (!(entryCoder instanceof KvCoder<?, ?>)) {
      throw new IllegalArgumentException("PCollection does not use a KvCoder");
    }
    @SuppressWarnings("unchecked")
    KvCoder<K, V> coder = (KvCoder<K, V>) entryCoder;
    return coder.getKeyCoder();
  }

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

  /** A utility class to help ensure coherence of tag and input PCollection types. */
  public static class TaggedKeyedPCollection<K, V> {

    final TupleTag<V> tupleTag;
    final PCollection<KV<K, V>> pCollection;

    public TaggedKeyedPCollection(TupleTag<V> tupleTag, PCollection<KV<K, V>> pCollection) {
      this.tupleTag = tupleTag;
      this.pCollection = pCollection;
    }

View on GitHub (pinned to 12126d8942)

Solutions

  1. Set a KvCoder on the PCollection before adding it to the KeyedPCollectionTuple
  2. Use KvCoder.of(keyCoder, valueCoder) and pc.setCoder(...) for inputs from custom IO
  3. Inspect pc.getCoder() type during debugging to confirm it is KvCoder

Example fix

// before
tuple.and(tag, pcWithoutKvCoder); // throws
// after
pc.setCoder(KvCoder.of(StringUtf8Coder.of(), valueCoder));
tuple.and(tag, pc);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(pc.getCoder() instanceof KvCoder)) { throw new IllegalArgumentException("KeyedPCollectionTuple input needs a KvCoder"); }

Type guard

if (pc.getCoder() instanceof KvCoder<?, ?> kvCoder) { return kvCoder.getKeyCoder(); }

Try / catch

try { return getKeyCoder(pc); } catch (IllegalArgumentException e) { pc.setCoder(KvCoder.of(defaultKeyCoder, defaultValueCoder)); return defaultKeyCoder; }

Prevention

When it happens

Trigger: Adding a PCollection to a KeyedPCollectionTuple whose coder is not a KvCoder, forcing getKeyCoder(pc) inference to fail — same root cause as error 556 but on KeyedPCollectionTuple.and()/getKeyCoder paths.

Common situations: Custom sources producing KVs without a KvCoder; PTransforms that set an explicit non-KvCoder coder on a KV PCollection before a join.

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 apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/5c9758f17a102198. Report an issue: GitHub.