apache/beam · error · java.lang.RuntimeException

cannot rehydrate Coder.

Error message

cannot rehydrate Coder.

What it means

During External.expand(), coders referenced by expanded output PCollections are rehydrated so Java can map them back to coder ids. An IOException from rehydratedComponents.getCoder(coderId) is caught and rethrown as this opaque RuntimeException, meaning the returned coder graph referenced a coder that could not be constructed.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/construction/External.java:333

                } catch (IOException e) {
                  throw new RuntimeException("cannot rehydrate PCollection.");
                }
              });
      externalPCollectionIdMap = externalPCollectionIdMapBuilder.build();

      Map<Coder<?>, String> externalCoderIdMapBuilder = new HashMap<>();
      expandedComponents
          .getPcollectionsMap()
          .forEach(
              (pcolId, pCol) -> {
                try {
                  String coderId = pCol.getCoderId();
                  if (isJavaSDKCompatible(expandedComponents, coderId)) {
                    Coder<?> coder = rehydratedComponents.getCoder(coderId);
                    externalCoderIdMapBuilder.putIfAbsent(coder, coderId);
                  }
                } catch (IOException e) {
                  throw new RuntimeException("cannot rehydrate Coder.");
                }
              });
      externalCoderIdMap = ImmutableMap.copyOf(externalCoderIdMapBuilder);

      return toOutputCollection(outputMapBuilder.build());
    }

    static Map<String, RunnerApi.Environment> resolveArtifacts(
        Map<String, RunnerApi.Environment> environments, Endpoints.ApiServiceDescriptor endpoint) {
      if (environments.size() == 0) {
        return environments;
      }
      ManagedChannel channel =
          ManagedChannelBuilder.forTarget(endpoint.getUrl())
              .usePlaintext()
              .maxInboundMessageSize(Integer.MAX_VALUE)
              .build();
      try {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Check isJavaSDKCompatible filtering and ensure the transform's outputs use Java-compatible coders.
  2. Align Beam SDK and expansion service versions so coder proto definitions match.
  3. Register the missing custom coder with the Java SDK (CoderProvider) so it can be constructed.
  4. Preserve the cause: `throw new RuntimeException("cannot rehydrate Coder.", e)` when editing this code path.

Example fix

// before
throw new RuntimeException("cannot rehydrate Coder.");
// after
throw new RuntimeException("cannot rehydrate Coder: " + coderId, e);
Defensive patterns

Strategy: try-catch

Validate before calling

null

Try / catch

try { external.expand(...); } catch (RuntimeException e) { if ("cannot rehydrate Coder.".equals(e.getMessage())) { /* check coder registration / SDK version skew */ } throw e; }

Prevention

When it happens

Trigger: The expansion response contains a pCollection whose coderId is absent from components.coders or whose payload cannot be parsed into a Java Coder during expansion of a cross-language transform.

Common situations: Cross-language transforms emitting coders unknown to the Java SDK; version skew between SDK and expansion service; custom coders not registered on the Java side.

Related errors


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