{"record":{"id":"d796f789340d851b","repo":"apache/beam","slug":"value-s-mutated-illegally-new-value-was-s-encoding-was-s-now","errorCode":null,"errorMessage":"Value %s mutated illegally, new value was %s. Encoding was %s, now %s.","messagePattern":"Value (.+?) mutated illegally, new value was (.+?)\\. Encoding was (.+?), now (.+?)\\.","errorType":"exception","errorClass":"IllegalMutationException","httpStatus":null,"severity":"critical","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/util/MutationDetectors.java","lineNumber":157,"sourceCode":"      T possiblyModifiedClonedValue = CoderUtils.clone(coder, possiblyModifiedObject);\n      Object newStructuralValue = coder.structuralValue(possiblyModifiedClonedValue);\n      if (originalStructuralValue.equals(newStructuralValue)) {\n        return;\n      } else if (Objects.deepEquals(\n          encodedOriginalObject, CoderUtils.encodeToByteArray(coder, possiblyModifiedObject))) {\n        LOG.warn(\n            \"{} of type {} has a #structuralValue method which does not return true when the \"\n                + \"encoding of the elements is equal. Element {}\",\n            Coder.class.getSimpleName(),\n            coder.getClass(),\n            possiblyModifiedObject);\n        return;\n      }\n      illegalMutation(clonedOriginalObject, possiblyModifiedClonedValue);\n    }\n\n    private void illegalMutation(T previousValue, T newValue) throws CoderException {\n      throw new IllegalMutationException(\n          String.format(\n              \"Value %s mutated illegally, new value was %s.\" + \" Encoding was %s, now %s.\",\n              previousValue,\n              newValue,\n              CoderUtils.encodeToBase64(coder, previousValue),\n              CoderUtils.encodeToBase64(coder, newValue)),\n          previousValue,\n          newValue);\n    }\n\n    @Override\n    public void close() {\n      verifyUnmodified();\n    }\n  }\n}\n","sourceCodeStart":139,"sourceCodeEnd":174,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/util/MutationDetectors.java#L139-L174","documentation":"IllegalMutationException signals that a value supposed to be immutable was changed after it was handed to Beam. The detector re-encodes both the original and current value; if the encodings differ, the value was mutated, which breaks Beam's assumption that elements are immutable and can corrupt pipelines.","triggerScenarios":"Calling verifyUnmodified()/close() on a MutationDetectors detector after mutating the element (e.g. modifying a List/Map field, changing a field of a POJO, mutating an Avro record in place).","commonSituations":"DoFns or transform code that mutates input elements before output; mutable collections in custom types; Java records/POJOs with setters used in pipeline elements.","solutions":["Do not mutate pipeline elements; create and emit a new instance with the changes.","Make element types deeply immutable (final fields, immutable collections, builder pattern).","Check collections inside elements — replace with immutable copies.","If mutation is intentional, emit a new value rather than reusing the mutated object."],"exampleFix":"// before\nvalue.getMetrics().add(x); // mutates element\n// after\nMyValue updated = value.toBuilder().addMetric(x).build();\nc.emit(updated);","handlingStrategy":"validation","validationCode":"// detect mutation before handing to Beam:\nbyte[] before = CoderUtils.encodeToBase64(coder, value);\n/* ... use value ... */\nif (!before.equals(CoderUtils.encodeToBase64(coder, value))) throw new IllegalStateException(\"element mutated\");","typeGuard":"// Java lacks runtime type guards; enforce at compile time:\n// declare element fields final, use List.copyOf()/Map.copyOf() wrappers","tryCatchPattern":"try { detector.close(); } catch (IllegalMutationException e) { log.error(\"Element mutated illegally: {}\", e.getMessage()); }","preventionTips":["Treat pipeline elements as deeply immutable","Use builder pattern or records for element types","Copy collections instead of mutating them","Never cache and mutate elements across output calls in DoFns"],"tags":["java","immutability","coders"],"backgroundTag":"invalid-state-transition","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}