t8y2/dbx · error · RuntimeException
Statement N failed: <cause message>
Error message
Statement N failed: <cause message>
What it means
When JDBC's executeBatch fails with a BatchUpdateException, tryExecuteBatch wraps it in a RuntimeException naming the statement index that failed (derived from the large update counts) and the driver's cause message. The original exception is preserved as the cause.
Source
Thrown at agents/common/src/main/java/com/dbx/agent/BatchExecutor.java:63
}
private static Long tryExecuteBatch(Connection conn, List<String> statements) throws Exception {
try (Statement stmt = conn.createStatement()) {
try {
int statementCount = 0;
for (String statement : statements) {
String trimmed = JdbcExecutor.trimSql(statement);
if (trimmed.isEmpty()) {
continue;
}
stmt.addBatch(trimmed);
statementCount++;
}
return statementCount == 0 ? 0L : affectedRows(executeBatch(stmt));
} catch (BatchUpdateException e) {
long[] counts = e.getLargeUpdateCounts();
int failedIndex = counts == null ? 1 : counts.length + 1;
throw new RuntimeException("Statement " + failedIndex + " failed: " + e.getMessage(), e);
} catch (SQLFeatureNotSupportedException | UnsupportedOperationException | AbstractMethodError e) {
return null;
}
}
}
private static long executeIndividually(Connection conn, List<String> statements) throws Exception {
long totalAffected = 0;
int statementIndex = 0;
try (Statement stmt = conn.createStatement()) {
for (String statement : statements) {
String trimmed = JdbcExecutor.trimSql(statement);
if (trimmed.isEmpty()) {
continue;
}
statementIndex++;
try {
if (!stmt.execute(trimmed)) {View on GitHub (pinned to c0390bff16)
Solutions
- Read the cause (getCause) and failed statement index from the message, fix the offending statement/data
- Validate batch inputs (uniqueness, types) before executing
- Split large batches to isolate failures and resubmit remaining statements
- Check driver support for large update counts (counts null implies index fallback)
- Enable rewrite-batch options compatible with your driver
Example fix
// before
stmt.addBatch("INSERT INTO t VALUES (?)"); // row 5 duplicates a key
long n = BatchExecutor.batchAffected(stmt); // RuntimeException: Statement 6 failed
// after
try {
long n = BatchExecutor.batchAffected(stmt);
} catch (RuntimeException e) {
int failedStmt = parseFailedIndex(e.getMessage());
dedupeRow(batch, failedStmt - 1);
resubmitRemaining(stmt, failedStmt);
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-validate batch rows
Set<Key> seen = new HashSet<>();
for (Row r : rows) {
if (!seen.add(r.key())) throw new IllegalArgumentException("duplicate key " + r.key());
} Try / catch
try {
long n = BatchExecutor.batchAffected(stmt);
} catch (RuntimeException e) {
if (e.getCause() instanceof BatchUpdateException) {
int failedIdx = parseIndex(e.getMessage()); // 'Statement N failed'
BatchUpdateException bue = (BatchUpdateException) e.getCause();
// inspect bue.getLargeUpdateCounts() and recover/resubmit from failedIdx
}
} Prevention
- Validate data (types, uniqueness, nullability) before batching
- Keep the cause chain: always inspect getCause() for the driver-level error
- Split very large batches to limit blast radius of a single bad statement
- Check for connection-drop errors which can also surface as BatchUpdateException
When it happens
Trigger: A batch statement fails at execution time: constraint violation, syntax error, type mismatch, or dead row in one of the batched statements; driver returns partial update counts.
Common situations: Bad data in one row of a bulk insert; duplicate key in batched upserts; SQL dialect mismatch on one statement; connection dropped mid-batch.
Related errors
- JDBC pool registry must be attached before connecting
- Not connected
- JDBC Session was quarantined while waiting for a connection
- Object source is not supported
- Completion assistant search is not supported by this agent
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/0ab6ad87fbc1b4b1.
Report an issue: GitHub.