risingwavelabs/risingwave · error

version field not set

Error message

version field not set

What it means

`ColumnCatalog::version()` returned `None` when `new_alter` builds the new `ColIdGenerator`, i.e. the original table's column catalog has no schema version (next_column_id / version_id) recorded. The generator needs the persisted version to compute the next column id and bumped version id, so a missing version is treated as a fatal invariant breach (expect/panic).

Source

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

            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 {
            existing,
            next_column_id: version.next_column_id,
            version_id: version.version_id + 1,
        }
    }

    /// Creates a new [`ColumnIdGenerator`] for a new table.
    pub fn new_initial() -> Self {
        Self {
            existing: Existing::new(),
            next_column_id: ColumnId::first_user_column(),
            version_id: INITIAL_TABLE_VERSION_ID,
        }
    }

    /// Generate [`ColumnId`]s for the given column and its nested fields (if any) recursively.

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Recreate the table so its catalog is rebuilt with a proper version field, then re-apply the ALTER.
  2. Backfill/migrate the persisted column catalog to include the version field.
  3. If this is a test fixture, construct the catalog via the normal create path so `version` is populated.

Example fix

// before: catalog built manually without version
let catalog = ColumnCatalog::from(col_descs);
// after: ensure version is set
let catalog = ColumnCatalog::from(col_descs).with_version(SchemaVersion::new(1));
Defensive patterns

Strategy: type-guard

Validate before calling

if original.version().is_none() {
    return Err("table catalog has no schema version; recreate the table".into());
}

Type guard

fn has_version(c: &ColumnCatalog) -> bool { c.version().is_some() }

Prevention

When it happens

Trigger: ALTER TABLE on a table whose `ColumnCatalog` was constructed without a `version` field — e.g. a table created by legacy code paths or CDC/ingest paths that never set the version, then altered.

Common situations: Upgrading an old deployment whose tables were created before schema versioning was introduced, or hand-crafted test catalogs omitting `version`.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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