risingwavelabs/risingwave · error

variant object cannot have duplicate field name `{field_name

Error message

variant object cannot have duplicate field name `{field_name}`

What it means

Variant objects (like JSON objects) require unique field names, but RisingWave struct types may contain duplicate field names. reject_duplicate_field compares each field name against the previous one (fields are iterated in name order) and bails when a consecutive duplicate is found.

Source

Thrown at src/common/src/types/variant.rs:728

                })
                .sorted_by(|a, b| a.0.cmp(&b.0))
                .collect_vec();
            for (field, value) in entries {
                let mut field_builder = ObjectFieldBuilder::new(field.as_str(), &mut object);
                append_datum_value(value, map_type.value(), &mut field_builder)?;
            }
            object.finish();
        }
        (value, ty) => bail!("cannot convert {} as {ty} to variant", value.get_ident()),
    }
    Ok(())
}

/// Variant objects require unique field names, but RisingWave struct types allow duplicates.
/// Callers iterate fields in name order, so comparing against the previous name suffices.
fn reject_duplicate_field(previous: Option<&str>, field_name: &str) -> anyhow::Result<()> {
    if previous == Some(field_name) {
        bail!("variant object cannot have duplicate field name `{field_name}`");
    }
    Ok(())
}

fn append_struct(
    value: super::StructRef<'_>,
    struct_type: &StructType,
    builder: &mut impl VariantBuilderExt,
) -> anyhow::Result<()> {
    let mut object = builder
        .try_new_object()
        .context("failed to create variant struct object")?;
    let fields = value
        .iter_fields_ref()
        .zip_eq_fast(struct_type.iter())
        .sorted_by(|(_, (field_a, _)), (_, (field_b, _))| field_a.cmp(field_b));
    let mut previous_field_name = None;
    for (value, (field_name, field_type)) in fields {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Rename one of the duplicate fields in the struct definition
  2. Deduplicate fields before conversion (drop or merge same-name fields)
  3. Change the struct definition so field names are unique

Example fix

// before
struct<a int,a varchar>  // duplicate 'a'
// after
struct<a int,a_str varchar>
Defensive patterns

Strategy: validation

Validate before calling

fn struct_fields_unique(ty: &StructType) -> bool {
    let mut names: Vec<_> = ty.names().collect();
    names.sort();
    names.windows(2).all(|w| w[0] != w[1])
}

Try / catch

if let Err(e) = append_struct(value, ty, &mut builder) {
    if e.to_string().contains("duplicate field name") {
        // rename fields or skip object export for this type
    } else { return Err(e); }
}

Prevention

When it happens

Trigger: Converting a RisingWave struct (or map) with duplicate field names to a Variant via append_struct / append_variant_value, e.g. `struct<a int,a varchar>`.

Common situations: Tables created with duplicate column names in nested structs (allowed in RW), then read/exported as JSON or Variant; JSON export jobs hitting this on legacy schemas.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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