Skip to content

Commit 389e68e

Browse files
committed
fix(pgwire): reject incomplete multi-statement batches with hard error
B1 (2026-08-26): batches >32 statements silently dropped the tail (batch 64 landed 32, batch 128 landed ~25%) with no error — clients believed work committed. Now any short response count returns XX000 'incomplete batch' so the client retries with a smaller batch. Defense-in-depth until the propose-path drop site is traced.
1 parent 82e1ab7 commit 389e68e

1 file changed

Lines changed: 20 additions & 0 deletions

File tree

‎nodedb/src/control/server/pgwire/handler/sql_exec.rs‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,31 @@ impl NodeDbPgHandler {
4343
.await
4444
}
4545
_ => {
46+
let total = statements.len();
4647
let mut all = Vec::new();
4748
for stmt in statements {
4849
let mut resp = self.execute_single_sql(identity, session_id, &stmt).await?;
4950
all.append(&mut resp);
5051
}
52+
// B1 ack reconciliation (2026-08-26): every statement must
53+
// produce at least one response. A short count means the
54+
// executor silently dropped work (observed: batch 64 → 32
55+
// landed, batch 128 → ~25%, no error). Surface it as a hard
56+
// error instead of letting the client believe the batch
57+
// committed. Defense-in-depth until the propose-path drop
58+
// site is traced and fixed.
59+
if all.len() < total {
60+
return Err(PgWireError::UserError(Box::new(ErrorInfo::new(
61+
"ERROR".to_owned(),
62+
"XX000".to_owned(),
63+
format!(
64+
"incomplete batch: {}/{} statements produced responses — \
65+
some work may have been dropped; retry with a smaller batch",
66+
all.len(),
67+
total,
68+
),
69+
))));
70+
}
5171
Ok(all)
5272
}
5373
}

0 commit comments

Comments
 (0)