prestodb/presto · error · PrestoException
GENERIC_INTERNAL_ERROR
GENERIC_INTERNAL_ERROR
Error message
unresolvable order for two inserts
What it means
ChangelogRecord.merge folds two changelog records into one during incremental changelog aggregation. When both records are INSERT operations there is no way to order them or break ties, so the state would be ambiguous. The code treats this as an unrecoverable internal inconsistency and throws GENERIC_INTERNAL_ERROR rather than producing silently wrong results.
Source
Thrown at presto-iceberg/src/main/java/com/facebook/presto/iceberg/function/changelog/ChangelogRecord.java:98
return lastOperation;
}
public ChangelogRecord merge(ChangelogRecord other)
{
if (other.lastOrdinal > lastOrdinal) {
this.lastOperation = other.lastOperation;
this.lastRow = other.lastRow;
this.lastOrdinal = other.lastOrdinal;
}
else if (other.lastOrdinal == lastOrdinal) {
// ordinals are equal. In the case both operations are inserts, we
// don't have a way to break ties. Likely an error, throw exception
ChangelogOperation operation = ChangelogOperation.valueOf(other.lastOperation.toStringUtf8().toUpperCase());
switch (operation) {
case UPDATE_AFTER:
case INSERT:
if (ChangelogOperation.valueOf(lastOperation.toStringUtf8().toUpperCase()).equals(INSERT)) {
throw new PrestoException(StandardErrorCode.GENERIC_INTERNAL_ERROR, "unresolvable order for two inserts");
}
lastOperation = other.lastOperation;
lastRow = other.lastRow;
lastOrdinal = other.lastOrdinal;
break;
case UPDATE_BEFORE:
case DELETE:
// we don't need to record data before a record update/delete
break;
default:
throw new PrestoException(StandardErrorCode.GENERIC_INTERNAL_ERROR, "unsupported operation type " + operation);
}
}
return this;
}
public void serialize(BlockBuilder out)
{View on GitHub (pinned to 55bb57d202)
Solutions
- Deduplicate upstream so only one INSERT per key reaches the aggregation (correct source keying on primary key).
- Ensure the changelog stream emits UPDATE_BEFORE/UPDATE_AFTER pairs instead of raw inserts for updates.
- If duplicates are expected from replays, enable idempotent/exactly-once consumption or filter replayed ordinals before aggregation.
- Report as a bug if it occurs with a well-formed single-writer CDC stream — the engine should never see two inserts for one key.
Defensive patterns
Strategy: validation
Validate before calling
// upstream: ensure exactly-once and primary-key keying for the CDC stream
// reject duplicate inserts before aggregation
if (seenKeys.putIfAbsent(record.key(), record.ordinal()) != null && record.op().equals("INSERT")) {
throw new IllegalStateException("duplicate insert for key " + record.key());
} Try / catch
try {
state.add(record);
} catch (PrestoException e) {
if (e.getErrorCode().getName().equals("GENERIC_INTERNAL_ERROR")) {
// restart aggregation from a clean checkpoint; do not retry into the same state
state = new ChangelogRecord(...);
}
} Prevention
- Key the changelog stream on the primary key.
- Deduplicate replayed events at the source.
- Emit proper update_before/update_after pairs instead of bare inserts.
When it happens
Trigger: Calling ChangelogRecord.add/merge with another record whose lastOperation is INSERT while this record's lastOperation is also INSERT — i.e. combining aggregation state from two separate inserts of the same key.
Common situations: Streaming changelog sources that emit duplicate inserts for the same primary key; re-emitted or replayed CDC events during source restarts; running changelog aggregation with incorrectly keyed partitions so two inserts collide in one aggregation group.
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/fc35c3d4ef5398f3.
Report an issue: GitHub.