risingwavelabs/risingwave · error · SinkError::Config
`max_batch_rows` must be between 1 and {}, got {}
Error message
`max_batch_rows` must be between 1 and {}, got {} What it means
The PostgreSQL sink validates that the `max_batch_rows` sink config option is between 1 and MAX_BATCH_ROWS_LIMIT. `validate()` runs when the sink is created (CREATE SINK). If the user supplied a value outside that inclusive range, the sink refuses to start with this config error.
Source
Thrown at src/connector/src/sink/postgres.rs:234
fn try_from(param: SinkParam) -> std::result::Result<Self, Self::Error> {
let schema = param.schema();
let pk_indices = param.downstream_pk_or_empty();
let config = PostgresConfig::from_btreemap(param.properties)?;
PostgresSink::new(config, schema, pk_indices, param.sink_type.is_append_only())
}
}
impl Sink for PostgresSink {
type LogSinker = BatchingLogSinker<PostgresSinkWriter>;
const SINK_NAME: &'static str = POSTGRES_SINK;
crate::impl_validate_sink_unknown_fields!();
async fn validate(&self) -> Result<()> {
if !(1..=MAX_BATCH_ROWS_LIMIT).contains(&self.config.max_batch_rows) {
return Err(SinkError::Config(anyhow!(
"`max_batch_rows` must be between 1 and {}, got {}",
MAX_BATCH_ROWS_LIMIT,
self.config.max_batch_rows
)));
}
if !self.is_append_only && self.pk_indices.is_empty() {
return Err(SinkError::Config(anyhow!(
"Primary key not defined for upsert Postgres sink (please define in `primary_key` field)"
)));
}
ensure_no_foreign_key(&self.config).await?;
// Verify our sink schema is compatible with Postgres
{
let pg_conn = self.config.pg_connection_config();
let pg_table = PostgresExternalTable::connect(View on GitHub (pinned to 6469eb736d)
Solutions
- Set `max_batch_rows` to a value between 1 and MAX_BATCH_ROWS_LIMIT in the WITH options of CREATE SINK.
- Remove the `max_batch_rows` option entirely to fall back to the default batch size.
- Check the current limit constant in src/connector/src/sink/postgres.rs before tuning.
Example fix
// before WITH (connector = 'postgres', max_batch_rows = 0) // after WITH (connector = 'postgres', max_batch_rows = 1024)
Defensive patterns
Strategy: validation
Validate before calling
let max_batch_rows: usize = 1024; assert!((1..=4294967295).contains(&max_batch_rows), "max_batch_rows must be between 1 and MAX_BATCH_ROWS_LIMIT");
Type guard
fn valid_batch_rows(v: i64) -> bool { v >= 1 } Prevention
- Clamp max_batch_rows to >= 1 when generating sink configs.
- Never use 0 to mean 'unbounded' for this option.
- Consult MAX_BATCH_ROWS_LIMIT in the source before tuning.
When it happens
Trigger: CREATE SINK ... WITH (connector='postgres', max_batch_rows = 0) or max_batch_rows set to a value greater than MAX_BATCH_ROWS_LIMIT; also a negative value.
Common situations: Copy-pasted config with max_batch_rows = 0 (thinking 0 means 'unlimited batching'); typos producing huge numbers; tuning batch size for throughput and overshooting the compile-time limit.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- `{}` must be {}, or {}
- Primary key not defined for upsert doris sink (please define
- Can't get fe host from url
- please set only one of the 'index_column' or 'index' propert
- please ensure the data type of {} is varchar.
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/660253080d07b47a.
Report an issue: GitHub.