apache/beam · error · ValueError

Not a KV coder: %s.

Error message

Not a KV coder: %s.

What it means

Coder.key_coder in apache_beam.coders is only valid on KV coders: for a non-KV coder, is_kv_coder() is False and this ValueError fires (while the KV-coder branch would raise NotImplementedError). It is a type guard ensuring callers only extract key coders from coders that actually encode key/value pairs; here it is reached from key_coder during coder composition.

Source

Thrown at sdks/python/apache_beam/coders/coders.py:263

    # it
    raise NotImplementedError

  @classmethod
  def from_type_hint(cls, unused_typehint, unused_registry):
    # type: (Type[CoderT], Any, CoderRegistry) -> CoderT
    # If not overridden, just construct the coder without arguments.
    return cls()

  def is_kv_coder(self):
    # type: () -> bool
    return False

  def key_coder(self):
    # type: () -> Coder
    if self.is_kv_coder():
      raise NotImplementedError('key_coder: %s' % self)
    else:
      raise ValueError('Not a KV coder: %s.' % self)

  def value_coder(self):
    # type: () -> Coder
    if self.is_kv_coder():
      raise NotImplementedError('value_coder: %s' % self)
    else:
      raise ValueError('Not a KV coder: %s.' % self)

  def _get_component_coders(self):
    # type: () -> Sequence[Coder]

    """For internal use only; no backwards-compatibility guarantees.

    Returns the internal component coders of this coder."""
    # This is an internal detail of the Coder API and does not need to be
    # refined in user-defined Coders.
    return []

View on GitHub (pinned to 12126d8942)

Solutions

  1. Only call key_coder() after checking coder.is_kv_coder()
  2. Use TupleCoder or a KV-aware coder for key/value data
  3. Restructure so key/value coders are obtained from the coder registry for KV PCollections

Example fix

// before
kc = coder.key_coder()  # coder may not be KV
// after
kc = coder.key_coder() if coder.is_kv_coder() else None
Defensive patterns

Strategy: validation

Validate before calling

if not coder.is_kv_coder():
    raise ValueError('expected a KV coder, got %s' % coder)

Type guard

def is_kv(coder):
    return coder.is_kv_coder()

Try / catch

try:
    kc = coder.key_coder()
except ValueError as e:
    log.error('%s', e)
    kc = None

Prevention

When it happens

Trigger: Calling coder.key_coder() on a non-KV coder (is_kv_coder() False), e.g. BytesCoder or a custom coder, from code that assumes elements are (key, value) tuples.

Common situations: Pipeline/framework code extracting key coders from arbitrary coders; users applying KV-only transforms to PCollection elements that are not key/value pairs.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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