{"record":{"id":"5941627773c6accd","repo":"apache/seatunnel","slug":"graph-operation-failed-594162","errorCode":"GRAPH_OPERATION_FAILED","errorMessage":"Mapping[%s/%s]: Failed to compute graph element ID for update","messagePattern":"Mapping\\[(.+?)/(.+?)\\]: Failed to compute graph element ID for update","errorType":"error_code","errorClass":"HugeGraphConnectorException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-hugegraph/src/main/java/org/apache/seatunnel/connectors/seatunnel/hugegraph/sink/HugeGraphSinkWriter.java","lineNumber":519,"sourceCode":"        }\n\n        if (before != null) {\n            for (MappingEntry entry : mappingEntries) {\n                // Only delete the pre-update element when this mapping produced a replacement\n                // after-image. If the after-image is absent (e.g. the after row has a null id\n                // field so map() returned null), deleting the old element would drop it with\n                // nothing written back — a silent data loss. Keeping the old element is the safe\n                // choice; a genuine removal should arrive as a DELETE changelog event.\n                if (!producedAfterImage.contains(entry)) {\n                    continue;\n                }\n                Object oldId;\n                Object newId;\n                try {\n                    oldId = entry.mapper.extractId(before);\n                    newId = entry.mapper.extractId(after);\n                } catch (Exception e) {\n                    throw new HugeGraphConnectorException(\n                            HugeGraphConnectorErrorCode.GRAPH_OPERATION_FAILED,\n                            String.format(\n                                    \"Mapping[%s/%s]: Failed to compute graph element ID for update\",\n                                    entry.config.getType(), entry.config.getLabel()),\n                            e);\n                }\n                if (oldId == null || oldId.equals(newId)) {\n                    continue;\n                }\n                Superseded s = new Superseded(entry, oldId);\n                if (entry.config.getType() == LabelType.VERTEX) {\n                    supersededVertices.add(s);\n                } else {\n                    supersededEdges.add(s);\n                }\n            }\n        }\n","sourceCodeStart":501,"sourceCodeEnd":537,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-hugegraph/src/main/java/org/apache/seatunnel/connectors/seatunnel/hugegraph/sink/HugeGraphSinkWriter.java#L501-L537","documentation":"During UPDATE handling, HugeGraphSinkWriter.buildUpdatePlan extracts the graph element IDs of both the BEFORE and AFTER row images via the mapping's extractor, and the underlying HugeGraph client/mapper threw while doing so. The connector cannot build the update plan (delete-old + write-new) without stable old/new IDs, so it fails the write with GRAPH_OPERATION_FAILED and wraps the original exception as the cause.","triggerScenarios":"A changelog row (UPDATE_BEFORE/UPDATE_AFTER) is written where entry.mapper.extractId(before) or extractId(after) throws: e.g. the ID field is absent, the configured id key does not exist in the row, or the mapper cannot coerce the row value to a valid HugeGraph ID.","commonSituations":"Source schema changed so the configured ID field no longer exists; ID field value is null or matches nullValues; mismatch between the mapping config (id_field / id keys) and the actual CDC payload; upstream emitted a schema evolution that the mapping was not updated for.","solutions":["Check the cause exception in the stack trace to see which field extraction failed.","Verify the mapping config's ID field name matches a non-null column present in both BEFORE and AFTER row images.","Update the mapping/sink config after any upstream schema change so the ID field still resolves.","Ensure nullValues configuration does not classify legitimate ID values as null."],"exampleFix":"// before: mapping references a dropped column\nmapping = { table_field = [\"id\", \"name\"], label = \"person\", id_field = \"uid\" }\n// after: align id_field with the actual schema\nmapping = { table_field = [\"uid\", \"name\"], label = \"person\", id_field = \"uid\" }","handlingStrategy":"validation","validationCode":"// before writing UPDATE rows, verify ID fields are present and non-null\nfor (Object v : new Object[]{before, after}) {\n    if (entry.mapper.extractId(v) == null) {\n        throw new IllegalArgumentException(\"ID field missing/null for \" + entry.config.getLabel());\n    }\n}","typeGuard":"boolean hasValidId(MappingEntry e, SeaTunnelRow r) { try { return e.mapper.extractId(r) != null; } catch (Exception ex) { return false; } }","tryCatchPattern":"try { plan = writer.plan(...); } catch (HugeGraphConnectorException ex) { if (ex.getErrorCode() == GRAPH_OPERATION_FAILED) { log.error(\"update plan failed\", ex.getCause()); /* route row to DLQ */ } }","preventionTips":["Keep mapping id_field config in sync with upstream schema","Re-validate mappings after any CDC schema evolution","Avoid nullValues entries covering ID columns"],"tags":["hugegraph","graph-sink","cdc-update","id-extraction"],"backgroundTag":"entity-not-found","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}