apache/seatunnel · error · HugeGraphConnectorException

GRAPH_OPERATION_FAILED

GRAPH_OPERATION_FAILED

Error message

Mapping[%s/%s]: Failed to compute graph element ID for update

What it means

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.

Solutions

  1. Check the cause exception in the stack trace to see which field extraction failed.
  2. Verify the mapping config's ID field name matches a non-null column present in both BEFORE and AFTER row images.
  3. Update the mapping/sink config after any upstream schema change so the ID field still resolves.
  4. Ensure nullValues configuration does not classify legitimate ID values as null.

Example fix

// before: mapping references a dropped column
mapping = { table_field = ["id", "name"], label = "person", id_field = "uid" }
// after: align id_field with the actual schema
mapping = { table_field = ["uid", "name"], label = "person", id_field = "uid" }
Defensive patterns

Strategy: validation

Validate before calling

// before writing UPDATE rows, verify ID fields are present and non-null
for (Object v : new Object[]{before, after}) {
    if (entry.mapper.extractId(v) == null) {
        throw new IllegalArgumentException("ID field missing/null for " + entry.config.getLabel());
    }
}

Type guard

boolean hasValidId(MappingEntry e, SeaTunnelRow r) { try { return e.mapper.extractId(r) != null; } catch (Exception ex) { return false; } }

Try / catch

try { plan = writer.plan(...); } catch (HugeGraphConnectorException ex) { if (ex.getErrorCode() == GRAPH_OPERATION_FAILED) { log.error("update plan failed", ex.getCause()); /* route row to DLQ */ } }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/5941627773c6accd. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-connectors-v2/connector-hugegraph/src/main/java/org/apache/seatunnel/connectors/seatunnel/hugegraph/sink/HugeGraphSinkWriter.java:519

        }

        if (before != null) {
            for (MappingEntry entry : mappingEntries) {
                // Only delete the pre-update element when this mapping produced a replacement
                // after-image. If the after-image is absent (e.g. the after row has a null id
                // field so map() returned null), deleting the old element would drop it with
                // nothing written back — a silent data loss. Keeping the old element is the safe
                // choice; a genuine removal should arrive as a DELETE changelog event.
                if (!producedAfterImage.contains(entry)) {
                    continue;
                }
                Object oldId;
                Object newId;
                try {
                    oldId = entry.mapper.extractId(before);
                    newId = entry.mapper.extractId(after);
                } catch (Exception e) {
                    throw new HugeGraphConnectorException(
                            HugeGraphConnectorErrorCode.GRAPH_OPERATION_FAILED,
                            String.format(
                                    "Mapping[%s/%s]: Failed to compute graph element ID for update",
                                    entry.config.getType(), entry.config.getLabel()),
                            e);
                }
                if (oldId == null || oldId.equals(newId)) {
                    continue;
                }
                Superseded s = new Superseded(entry, oldId);
                if (entry.config.getType() == LabelType.VERTEX) {
                    supersededVertices.add(s);
                } else {
                    supersededEdges.add(s);
                }
            }
        }

View on GitHub (pinned to cf67b549a7)