risingwavelabs/risingwave · error

The `n` must be set with `bucket` and `truncate`

Error message

The `n` must be set with `bucket` and `truncate`

What it means

When parsing a `bucket(...)` or `truncate(...)` partition transform, the `n` (parameter count/width) capture group is mandatory. If the regex matched a `bucket`/`truncate` transform but the optional `n` group is absent, the code errors with `The n must be set with bucket and truncate`.

Source

Thrown at src/connector/src/sink/iceberg/create_table.rs:463

    if !re.is_match(&expr) {
        bail!(format!(
            "Invalid partition fields: {}\nHINT: Supported formats are column, transform(column), transform(n,column), transform(n, column)",
            expr
        ))
    }
    let caps = re.captures_iter(&expr);

    let mut partition_columns = vec![];

    for mat in caps {
        let (column, transform) = if mat.name("n").is_none() && mat.name("field").is_none() {
            (&mat["transform"], Transform::Identity)
        } else {
            let mut func = mat["transform"].to_owned();
            if func == "bucket" || func == "truncate" {
                let n = &mat
                    .name("n")
                    .ok_or_else(|| anyhow!("The `n` must be set with `bucket` and `truncate`"))?
                    .as_str();
                func = format!("{func}[{n}]");
            }
            (
                &mat["field"],
                Transform::from_str(&func)
                    .with_context(|| format!("invalid transform function {}", func))?,
            )
        };
        partition_columns.push((column.to_owned(), transform));
    }
    Ok(partition_columns)
}

pub fn parse_order_key_exprs(
    expr: String,
) -> std::result::Result<Vec<IcebergOrderKeyField>, anyhow::Error> {
    let mut order_keys = Vec::new();

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Add the numeric parameter: use `bucket(N, col)` and `truncate(W, col)` with N/W as integers.
  2. Use parameterless transforms (`year(col)`, `month(col)`, `day(col)`, `hour(col)`) if no n is intended.
  3. Re-run sink creation with the corrected `partition_by` option.

Example fix

// before
partition_by = 'bucket(id)'
// after
partition_by = 'bucket(16, id)'
Defensive patterns

Strategy: validation

Validate before calling

// ensure bucket/truncate always carry their numeric parameter
fn validate_partition_expr(e: &str) -> Result<(), String> {
    for part in e.split(',') {
        let p = part.trim();
        if (p.starts_with("bucket(") || p.starts_with("truncate("))
            && !p.contains(',') {
            return Err(format!("{p} needs an n parameter: e.g. bucket(16, col)"));
        }
    }
    Ok(())
}

Prevention

When it happens

Trigger: Called from `parse_partition_by_exprs`: an expression like `bucket(id)` or `truncate(name)` where the transform requires a numeric parameter (bucket count / truncate width) but none was provided between the parentheses.

Common situations: Users copy Spark's `truncate(col)`-style syntax without the width, or write `bucket(col)` forgetting the bucket count; mixing up Iceberg's parameterized transforms with parameterless ones (year/month/day/hour).

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/1bb85c17a87c77f9. Report an issue: GitHub.