risingwavelabs/risingwave · error

Invalid value for

Error message

Invalid value for {}

What it means

When creating a CDC table, the 'backfill_enable' with-option must be parseable as a boolean ('true'/'false'). RisingWave calls bool::from_str on the option value, and when parsing fails it throws this error because the option value cannot be interpreted as a boolean. The option controls whether the CDC table backfills existing data from the upstream source on creation.

Solutions

  1. Set backfill_enable to exactly 'true' or 'false' in the WITH clause.
  2. Remove the option entirely to use the default (backfill enabled).
  3. Check for typos or stray whitespace/quotes in the option value.

Example fix

// before
CREATE TABLE t ... WITH (connector='cdc-postgres', backfill_enable = 'yes');
// after
CREATE TABLE t ... WITH (connector='cdc-postgres', backfill_enable = 'false');
Defensive patterns

Strategy: validation

Validate before calling

// SQL-side check before DDL
const v = opts.backfill_enable;
if (v !== undefined && v !== 'true' && v !== 'false') {
  throw new Error(`backfill_enable must be 'true' or 'false', got: ${v}`);
}

Type guard

const isRwBool = (s: unknown): s is 'true' | 'false' => s === 'true' || s === 'false';

Prevention

When it happens

Trigger: CREATE TABLE ... WITH (connector = 'cdc-...', backfill_enable = 'yes') or any value other than exactly 'true' or 'false' (case-sensitive: 'True', '1', '0' also fail) passed to gen_create_table_plan_for_cdc_table.

Common situations: Using truthy strings like 'yes', 'on', '1', or capitalized 'True' in the WITH clause; quoting mistakes; copying options from other systems that accept 1/0.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src/frontend/src/optimizer/plan_node/generic/cdc_scan.rs:72

}

pub fn build_cdc_scan_options_with_options(
    with_options: &WithOptions,
    cdc_table_type: &ExternalCdcTableType,
) -> Result<CdcScanOptions> {
    // Update this after more CDC table type is supported for backfill v2.
    let support_backfill_v2 = matches!(
        cdc_table_type,
        ExternalCdcTableType::Postgres | ExternalCdcTableType::Mock
    );

    // unspecified option will use default values
    let mut scan_options = CdcScanOptions::default();

    // disable backfill if 'snapshot=false'
    if let Some(snapshot) = with_options.get(CDC_BACKFILL_ENABLE_KEY) {
        scan_options.disable_backfill = !(bool::from_str(snapshot)
            .map_err(|_| anyhow!("Invalid value for {}", CDC_BACKFILL_ENABLE_KEY))?);
    };

    if let Some(snapshot_interval) = with_options.get(CDC_BACKFILL_SNAPSHOT_INTERVAL_KEY) {
        scan_options.snapshot_barrier_interval = u32::from_str(snapshot_interval)
            .map_err(|_| anyhow!("Invalid value for {}", CDC_BACKFILL_SNAPSHOT_INTERVAL_KEY))?;
    };

    if let Some(snapshot_batch_size) = with_options.get(CDC_BACKFILL_SNAPSHOT_BATCH_SIZE_KEY) {
        scan_options.snapshot_batch_size = u32::from_str(snapshot_batch_size)
            .map_err(|_| anyhow!("Invalid value for {}", CDC_BACKFILL_SNAPSHOT_BATCH_SIZE_KEY))?;
    };

    if support_backfill_v2 {
        if let Some(backfill_parallelism) = with_options.get(CDC_BACKFILL_PARALLELISM) {
            scan_options.backfill_parallelism = u32::from_str(backfill_parallelism)
                .map_err(|_| anyhow!("Invalid value for {}", CDC_BACKFILL_PARALLELISM))?;
            if scan_options.backfill_parallelism > CDC_BACKFILL_MAX_PARALLELISM {
                return Err(anyhow!(

View on GitHub (pinned to 6469eb736d)