{"record":{"id":"f6dadb313be7bd68","repo":"apache/beam","slug":"mutation-does-not-have-an-operation-type-set","errorCode":null,"errorMessage":"Mutation {} does not have an operation type set.","messagePattern":"Mutation (.+?) does not have an operation type set\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/datastore/DatastoreV1.java","lineNumber":2334,"sourceCode":"              c.getPipelineOptions(), projectId.get(), databaseIdOrDefaultDatabase, localhost);\n      writeBatcher.start();\n      if (adaptiveThrottler == null) {\n        // Initialize throttler at first use, because it is not serializable.\n        adaptiveThrottler = new AdaptiveThrottler(120000, 10000, 1.25);\n      }\n    }\n\n    private static com.google.datastore.v1.Key getKey(Mutation m) {\n      if (m.hasUpsert()) {\n        return m.getUpsert().getKey();\n      } else if (m.hasInsert()) {\n        return m.getInsert().getKey();\n      } else if (m.hasDelete()) {\n        return m.getDelete();\n      } else if (m.hasUpdate()) {\n        return m.getUpdate().getKey();\n      } else {\n        LOG.warn(\"Mutation {} does not have an operation type set.\", m);\n        return Entity.getDefaultInstance().getKey();\n      }\n    }\n\n    @ProcessElement\n    public void processElement(ProcessContext c, BoundedWindow window) throws Exception {\n      Mutation mutation = c.element();\n      int size = mutation.getSerializedSize();\n      ProcessContextAdapter<OutT> contextAdapter = new ProcessContextAdapter<>(c);\n      com.google.datastore.v1.Key key = getKey(mutation);\n\n      if (!uniqueMutationKeys.add(key)) {\n        flushBatch(contextAdapter);\n        checkState(\n            uniqueMutationKeys.add(key), \"Key %s still present in batch after flushing.\", key);\n      }\n\n      if (mutations.size() > 0","sourceCodeStart":2316,"sourceCodeEnd":2352,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/datastore/DatastoreV1.java#L2316-L2352","documentation":"When extracting the key from a Mutation (for deduplication/ordering in the Datastore write path), the connector checks for insert, update, and delete operations. If a Mutation has none of these set, the connector logs this warning and substitutes Entity.getDefaultInstance().getKey() as a placeholder, so the malformed mutation proceeds with a meaningless key rather than crashing the pipeline.","triggerScenarios":"Building a Mutation via the V1 entity/Mutation helpers without calling setUpsert/setInsert/setDelete/setUpdate — e.g. an empty Mutation.newBuilder() passed to DatastoreIO.v1().write() or V1.makeUpdate/Mutation pieces dropped during serialization.","commonSituations":"Users constructing Mutations manually from protobufs and forgetting to set the oneof operation; entities whose upsert field was lost in a transform or serialization step; all-keys detection where a Mutation intentionally holds only a key.","solutions":["Ensure every Mutation you emit has exactly one operation set: use DatastoreHelper.makeUpsert(entity), makeInsert, makeUpdate, or makeDelete instead of hand-building Mutation.newBuilder().","Filter out empty/default Mutation instances before writing to DatastoreIO.v1().write().","Inspect the logged Mutation object to find where the operation type was lost in your pipeline."],"exampleFix":"// before\nMutation m = Mutation.newBuilder().build();\n// after\nMutation m = DatastoreHelper.makeUpsert(Entity.newBuilder().setKey(key).build());","handlingStrategy":"validation","validationCode":"// Java: drop mutations without an operation\nif (com.google.datastore.v1.Mutation.getDefaultInstance().equals(m)\n    || (!m.hasInsert() && !m.hasUpdate() && !m.hasUpsert() && !m.hasDelete())) {\n  return; // skip before writing\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always use DatastoreHelper.makeUpsert/makeInsert/makeUpdate/makeDelete to build mutations.","Never emit raw Mutation.newBuilder() instances into the write sink.","Unit-test that every element mapped to a Mutation has exactly one operation set."],"tags":["gcp-datastore","mutation","empty-mutation","beam-io"],"backgroundTag":"missing-required-argument","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}