prestodb/presto · error · BatchUpdateException

e.getMessage()

Error message

e.getMessage()

What it means

When executeBatch encounters a failure for one statement in the batch, it wraps the SQLException in a java.sql.BatchUpdateException, copying message, SQLState, errorCode and cause, with update counts for statements executed so far. The message shown is just the underlying failure's message re-raised as a batch exception.

Source

Thrown at presto-jdbc/src/main/java/com/facebook/presto/jdbc/PrestoPreparedStatement.java:468

        checkOpen();
        batchValues.clear();
        isBatch = false;
    }

    @Override
    public int[] executeBatch()
            throws SQLException
    {
        try {
            int[] batchUpdateCounts = new int[batchValues.size()];
            for (int i = 0; i < batchValues.size(); i++) {
                try {
                    super.execute(getExecuteSql(statementName, batchValues.get(i)));
                    batchUpdateCounts[i] = getUpdateCount();
                }
                catch (SQLException e) {
                    long[] updateCounts = Arrays.stream(batchUpdateCounts).mapToLong(j -> j).toArray();
                    throw new BatchUpdateException(e.getMessage(), e.getSQLState(), e.getErrorCode(), updateCounts, e.getCause());
                }
            }
            return batchUpdateCounts;
        }
        finally {
            clearBatch();
        }
    }

    @Override
    public void setCharacterStream(int parameterIndex, Reader reader, int length)
            throws SQLException
    {
        throw new NotImplementedException("PreparedStatement", "setCharacterStream");
    }

    @Override
    public void setRef(int parameterIndex, Ref x)

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Inspect BatchUpdateException.getUpdateCounts() to identify which statement(s) failed.
  2. Log e.getCause() — the original SQLException carries the real server error detail.
  3. Validate parameter types/values before addBatch to reject bad rows early.
  4. Execute statements individually to pinpoint the failing statement when diagnosing.

Example fix

// before
ps.executeBatch();
// after
try {
    ps.executeBatch();
} catch (BatchUpdateException e) {
    long[] counts = e.getUpdateCounts();
    LOG.error("batch failed at index {} cause: {}", counts.length, e.getCause(), e);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// validate each batched parameter before addBatch
for (Object p : row) {
    if (p != null && !(p instanceof String || p instanceof Number || p instanceof java.sql.Date || p instanceof java.sql.Time || p instanceof java.sql.Timestamp)) {
        throw new IllegalArgumentException("bad batch param type: " + p.getClass());
    }
}

Try / catch

try { ps.executeBatch(); } catch (BatchUpdateException e) { long[] counts = e.getUpdateCounts(); SQLException cause = (SQLException) e.getCause(); LOG.error("batch failed; executed={} sqlState={} cause={}", counts.length, e.getSQLState(), cause, e); }

Prevention

When it happens

Trigger: Calling executeBatch() after addBatch()/addBatch(sql) on a PrestoPreparedStatement where any batched statement fails (e.g. syntax error, type mismatch, constraint/verification failure on statement i).

Common situations: Bulk inserts where one row's value violates a column type; partial batches where the first N statements succeeded and later ones failed — inspect getUpdateCounts() to see how far execution got.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/58ec820a14648f59. Report an issue: GitHub.