risingwavelabs/risingwave · error

unexpected default value type for real

Error message

unexpected default value type for real

What it means

derive_default_value converts a MySQL floating-point default (ColumnDefault::Real) only into Float32, Float64, or Decimal. If the target column's RW DataType is anything else, the code bails with 'unexpected default value type for real'. This is a defensive check against mapping an f64 default into an incompatible column type.

Solutions

  1. Align the MySQL column's DEFAULT with its type (numeric default only on numeric columns).
  2. Change the column default in MySQL to a compatible constant (e.g. integer default for an integer column).
  3. Adjust connector type mapping so the column maps to Float32/Float64/Decimal.

Example fix

// before (MySQL)
ALTER TABLE t MODIFY qty INT DEFAULT 1.5;
// after
ALTER TABLE t MODIFY qty INT DEFAULT 1;
Defensive patterns

Strategy: validation

Validate before calling

SELECT COLUMN_NAME, COLUMN_TYPE, COLUMN_DEFAULT FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='mydb' AND TABLE_NAME='t'
  AND COLUMN_DEFAULT IS NOT NULL
  AND COLUMN_DEFAULT LIKE '%.%'
  AND NOT (COLUMN_TYPE LIKE 'float%' OR COLUMN_TYPE LIKE 'double%' OR COLUMN_TYPE LIKE 'decimal%');

Type guard

function realDefaultIsCompatible(mysqlColumnType, rwDataType) {
  return /^(float|double|decimal)/.test(mysqlColumnType) &&
    ["Float32","Float64","Decimal"].includes(rwDataType);
}

Try / catch

try { await createCdcTable('t'); } catch (e) { if (String(e).includes('unexpected default value type for real')) { /* make the MySQL default a constant of the column's own type */ } else throw e; }

Prevention

When it happens

Trigger: A MySQL column with a real/floating default value (e.g. DEFAULT 1.5) whose mapped RW type is not Float32, Float64, or Decimal.

Common situations: Schema changes re-typing a float column to int/string while keeping the old default; type-mapping discrepancies between MySQL and RW (e.g. FLOAT mapped unexpectedly).

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at src/connector/src/source/cdc/external/mysql.rs:242

    let datum = match default {
        ColumnDefault::Null => None,
        ColumnDefault::Int(val) => match data_type {
            DataType::Int16 => Some(ScalarImpl::Int16(val as _)),
            DataType::Int32 => Some(ScalarImpl::Int32(val as _)),
            DataType::Int64 => Some(ScalarImpl::Int64(val)),
            DataType::Varchar => {
                // should be the Enum type which is mapped to Varchar
                Some(ScalarImpl::from(val.to_string()))
            }
            _ => bail!("unexpected default value type for integer"),
        },
        ColumnDefault::Real(val) => match data_type {
            DataType::Float32 => Some(ScalarImpl::Float32(F32::from(val as f32))),
            DataType::Float64 => Some(ScalarImpl::Float64(val.into())),
            DataType::Decimal => Some(ScalarImpl::Decimal(
                Decimal::try_from(val).context("failed to convert default value to decimal")?,
            )),
            _ => bail!("unexpected default value type for real"),
        },
        ColumnDefault::String(mut val) => {
            // mysql timestamp is mapped to timestamptz, we use UTC timezone to
            // interpret its value
            if data_type == &DataType::Timestamptz {
                val = timestamp_val_to_timestamptz(val.as_str())?;
            }
            Some(ScalarImpl::from_text(val.as_str(), data_type).map_err(|e| anyhow!(e)).context(
                "failed to parse mysql default value expression, only constant is supported",
            )?)
        }
        ColumnDefault::CurrentTimestamp | ColumnDefault::CustomExpr(_) => {
            bail!("MySQL CURRENT_TIMESTAMP and custom expression default value not supported")
        }
    };
    Ok(datum)
}

View on GitHub (pinned to 6469eb736d)