apache/beam · error · RuntimeException

RuntimeException

Error message

RuntimeException

What it means

MutationDetectors' verifyUnmodified re-encodes the original value and compares it with the possibly-mutated value to detect illegal mutations. CoderException (a checked exception) can occur while re-encoding; since verifyUnmodified cannot throw checked exceptions, it is wrapped in a plain RuntimeException.

Solutions

  1. Inspect getCause() for the underlying CoderException.
  2. Ensure your coder is deterministic and can encode both the original and cloned value.
  3. Use a deep copy or re-create the value instead of mutating it before close().

Example fix

// before
detector.verifyUnmodified();
// after
try { detector.verifyUnmodified(); } catch (RuntimeException e) { throw new RuntimeException(e.getCause()); }
Defensive patterns

Strategy: try-catch

Validate before calling

// before verifyUnmodified:
// byte[] orig = CoderUtils.encodeToBase64(coder, value);
// CoderUtils.decodeFromBase64(coder, orig); // ensure coder round-trips

Type guard

null

Try / catch

try { detector.verifyUnmodified(); } catch (RuntimeException e) { CoderException ce = (CoderException) e.getCause(); /* handle coder failure */ }

Prevention

When it happens

Trigger: Calling verifyUnmodified() (directly or via close()) on a CheckedMutationDetector when the coder fails to encode the original or cloned value — e.g. a value whose encoded form the coder cannot round-trip.

Common situations: Custom coders that are non-deterministic or fail on cloned values; elements whose encoding changed between Beam versions.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/MutationDetectors.java:130

     */
    public CodedValueMutationDetector(T value, Coder<T> coder) throws CoderException {
      this.coder = coder;
      // We need to clone the original value before getting it's structural value.
      // If the object is consistent with equals, the Structural value will be the
      // exact same object reference making it impossible to detect changes.
      clonedOriginalValue = CoderUtils.clone(coder, value);
      this.originalStructuralValue = coder.structuralValue(clonedOriginalValue);
      this.possiblyModifiedObject = value;
      this.encodedOriginalObject = CoderUtils.encodeToByteArray(coder, value);
      this.clonedOriginalObject = CoderUtils.decodeFromByteArray(coder, encodedOriginalObject);
    }

    @Override
    public void verifyUnmodified() {
      try {
        verifyUnmodifiedThrowingCheckedExceptions();
      } catch (CoderException exn) {
        throw new RuntimeException(exn);
      }
    }

    private void verifyUnmodifiedThrowingCheckedExceptions() throws CoderException {
      // Since there is no guarantee that cloning an object via the coder will
      // return the exact same type as value, We are cloning the possiblyModifiedObject
      // before getting it's structural value. This way we are guaranteed to compare the same
      // types.
      T possiblyModifiedClonedValue = CoderUtils.clone(coder, possiblyModifiedObject);
      Object newStructuralValue = coder.structuralValue(possiblyModifiedClonedValue);
      if (originalStructuralValue.equals(newStructuralValue)) {
        return;
      } else if (Objects.deepEquals(
          encodedOriginalObject, CoderUtils.encodeToByteArray(coder, possiblyModifiedObject))) {
        LOG.warn(
            "{} of type {} has a #structuralValue method which does not return true when the "
                + "encoding of the elements is equal. Element {}",
            Coder.class.getSimpleName(),

View on GitHub (pinned to 12126d8942)