risingwavelabs/risingwave · error

duplicate path: {:?}

Error message

duplicate path: {:?}

What it means

Panic inside `Existing::try_insert` during column-id collection: the same fully-qualified column path (e.g. a nested struct field path) was encountered twice while gathering the columns of the table being altered. `Existing` is a map from column path to (column_id, data_type), and a duplicate path means the original schema contains two columns resolving to the identical nested path, which is an invariant violation.

Source

Thrown at src/frontend/src/handler/create_table/col_id_gen.rs:117

                        handle(existing, path, ColumnId::placeholder(), list.elem().clone());
                    });
                }
                DataType::Map(map) => {
                    // There's no id for the key/value as map's own structure won't change.
                    with_segment!(Segment::MapKey, {
                        handle(existing, path, ColumnId::placeholder(), map.key().clone());
                    });
                    with_segment!(Segment::MapValue, {
                        handle(existing, path, ColumnId::placeholder(), map.value().clone());
                    });
                }

                data_types::simple!() => {}
            }

            existing
                .try_insert(path.clone(), (id, data_type))
                .unwrap_or_else(|_| panic!("duplicate path: {:?}", path));
        }

        let mut existing = Existing::new();

        // Collect all existing fields into `existing`.
        for col in original.columns() {
            let mut path = vec![Segment::Field(col.name().to_owned())];
            handle(
                &mut existing,
                &mut path,
                col.column_id(),
                col.data_type().clone(),
            );
        }

        let version = original.version().expect("version field not set");

        Self {

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Inspect `SHOW CREATE TABLE` / the catalog for duplicate column or nested-field names and rename or drop one of them before altering.
  2. Recreate the table (create new, INSERT from old, swap names) if the catalog is already corrupted.
  3. If hit during development, add a uniqueness assertion when building the column list so the collision is caught at bind time instead of a panic.

Example fix

// before: ALTER TABLE t ADD COLUMN v struct<a int> while a path collision exists
// after: drop the conflicting column first
ALTER TABLE t DROP COLUMN v;
ALTER TABLE t ADD COLUMN v struct<a int>;
Defensive patterns

Strategy: validation

Validate before calling

let mut seen = std::collections::HashSet::new();
for col in original.columns() {
    // walk nested fields and collect paths; assert no duplicates before ALTER
    if !seen.insert(col.name().to_string()) {
        return Err(format!("duplicate column path: {}", col.name()));
    }
}

Prevention

When it happens

Trigger: Calling ALTER TABLE (via `new_alter` -> `handle`) on a table whose original columns produce two identical paths — e.g. a nested struct field path collides with another column path after case/normalization, or a corrupted catalog storing two fields at the same path.

Common situations: Altering a table whose schema was mutated by another concurrent ALTER, restoring a table from a catalog snapshot with duplicated nested fields, or bugs in schema evolution producing two struct fields with the same name at the same nesting level.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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