risingwavelabs/risingwave · critical

failed to parse relation definition

Error message

failed to parse relation definition

What it means

During ALTER ... RENAME, the stored relation definition SQL is re-parsed; if parsing fails the code panics via .expect("failed to parse relation definition"). Empty definitions are special-cased earlier (CTAS tables), so reaching the expect means the stored definition is non-empty but unparseable.

Source

Thrown at src/meta/src/controller/rename.rs:38

    Array, CdcTableInfo, CreateSink, CreateSinkStatement, CreateSourceStatement,
    CreateSubscriptionStatement, Distinct, Expr, Function, FunctionArg, FunctionArgExpr,
    FunctionArgList, Ident, ObjectName, Query, SelectItem, SetExpr, Statement, TableAlias,
    TableFactor, TableWithJoins, Window,
};
use risingwave_sqlparser::parser::Parser;

/// `alter_relation_rename` renames a relation to a new name in its `Create` statement, and returns
/// the updated definition raw sql. Note that the `definition` must be a `Create` statement and the
/// `new_name` must be a valid identifier, it should be validated before calling this function. To
/// update all relations that depend on the renamed one, use `alter_relation_rename_refs`.
pub fn alter_relation_rename(definition: &str, new_name: &str) -> String {
    // This happens when we try to rename a table that's created by `CREATE TABLE AS`. Remove it
    // when we support `SHOW CREATE TABLE` for `CREATE TABLE AS`.
    if definition.is_empty() {
        tracing::warn!("found empty definition when renaming relation, ignored.");
        return definition.into();
    }
    let ast = Parser::parse_sql(definition).expect("failed to parse relation definition");
    let mut stmt =
        Itertools::exactly_one(ast.into_iter()).expect("should contains only one statement");

    match &mut stmt {
        Statement::CreateTable { name, .. }
        | Statement::CreateView { name, .. }
        | Statement::CreateIndex { name, .. }
        | Statement::CreateSource {
            stmt: CreateSourceStatement {
                source_name: name, ..
            },
        }
        | Statement::CreateSubscription {
            stmt:
                CreateSubscriptionStatement {
                    subscription_name: name,
                    ..
                },

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Inspect the relation's stored definition in the meta store and fix or restore it.
  2. If the definition is invalid and the relation is droppable, drop and re-create the relation with a valid definition.
  3. Report the unparseable definition text upstream — it indicates a parser-version compatibility bug.
Defensive patterns

Strategy: validation

Validate before calling

// Before rename, ensure the stored definition parses
let ast = Parser::parse_sql(definition).map_err(|e| anyhow!(e))?;
if ast.len() != 1 { bail!("definition must be a single statement"); }

Type guard

fn is_renamable_definition(d: &str) -> bool {
    !d.is_empty() && Parser::parse_sql(d).map(|a| a.len()) == Ok(1)
}

Try / catch

// expect() panics; guard at the boundary
std::panic::catch_unwind(|| alter_relation_rename(def, from, to))

Prevention

When it happens

Trigger: alter_relation_rename on a relation whose persisted `definition` column is corrupted, truncated, or was written by an older/incompatible parser version that the current risingwave_sqlparser cannot parse.

Common situations: Manual meta store edits, upgrade across parser grammar changes, partially written definition rows, or non-CREATE definitions stored for exotic relations.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


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