{"record":{"id":"3bcec6d12805c977","repo":"risingwavelabs/risingwave","slug":"expect-create-table-or-create-source-statement","errorCode":null,"errorMessage":"expect `CREATE TABLE` or `CREATE SOURCE` statement, found: `{base:?}`","messagePattern":"expect `CREATE TABLE` or `CREATE SOURCE` statement, found: `(.+?)`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/frontend/src/catalog/purify.rs","lineNumber":86,"sourceCode":"    let (Statement::CreateTable {\n        columns: column_defs,\n        constraints,\n        wildcard_idx,\n        include_column_options,\n        ..\n    }\n    | Statement::CreateSource {\n        stmt:\n            CreateSourceStatement {\n                columns: column_defs,\n                constraints,\n                wildcard_idx,\n                include_column_options,\n                ..\n            },\n    }) = &mut base\n    else {\n        bail!(\"expect `CREATE TABLE` or `CREATE SOURCE` statement, found: `{base:?}`\");\n    };\n\n    // First, remove the wildcard from the definition.\n    *wildcard_idx = None;\n\n    // Filter out columns that are not defined by users in SQL.\n    let defined_columns = columns.iter().filter(|c| c.is_defined_in_columns_clause());\n\n    // Derive `ColumnDef` from `ColumnCatalog`.\n    let mut purified_column_defs = Vec::new();\n    for column in defined_columns {\n        let mut column_def = if let Some(existing) = column_defs\n            .iter()\n            .find(|c| c.name.real_value() == column.name())\n        {\n            // If the column is already defined in the persisted definition, retrieve it.\n            existing.clone()\n        } else {","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/frontend/src/catalog/purify.rs#L68-L104","documentation":"In `try_purify_table_source_create_sql_ast`, RisingWave purifies a parsed CREATE statement (removing wildcards and connector-injected columns) to rebuild table/source definitions. The let-else only accepts `CREATE TABLE` or `CREATE SOURCE` ASTs; anything else bails with this message including the debug repr of the statement.","triggerScenarios":"Calling `try_purify_table_source_create_sql_ast` (directly or via `create_sql_ast_purified` / `get_new_table_definition_for_cdc_table`) with a parsed statement that is not CREATE TABLE/CREATE SOURCE, e.g. CREATE MATERIALIZED VIEW, CREATE SINK, or an ALTER statement.","commonSituations":"Internal tooling or CDC table-definition re-resolution fed the wrong statement kind; schema-change flows storing/reading a persisted SQL string that was later changed to a non-TABLE/SOURCE statement.","solutions":["Ensure the SQL string passed to purification is a `CREATE TABLE` or `CREATE SOURCE` statement.","Check what produced the persisted/derived SQL and why its statement kind changed (e.g. version migration or manual edit of persisted definition).","Guard the call site: only invoke purification for table/source creation paths."],"exampleFix":"// before\nlet ast = parse(sql);\nlet purified = try_purify_table_source_create_sql_ast(ast)?; // sql was CREATE MATERIALIZED VIEW\n// after\nassert!(sql.trim_start().to_uppercase().starts_with(\"CREATE TABLE\") || sql.trim_start().to_uppercase().starts_with(\"CREATE SOURCE\"));\nlet purified = try_purify_table_source_create_sql_ast(parse(sql))?;","handlingStrategy":"validation","validationCode":"const upper = sql.trimStart().toUpperCase();\nif (!upper.startsWith(\"CREATE TABLE\") && !upper.startsWith(\"CREATE SOURCE\")) {\n  throw new Error(\"purification requires CREATE TABLE or CREATE SOURCE\");\n}","typeGuard":"function isPurifiableStatement(ast) {\n  return ast && (ast.statement.CreateTable !== undefined || ast.statement.CreateSource !== undefined);\n}","tryCatchPattern":"match try_purify_table_source_create_sql_ast(ast) {\n    Err(e) if e.to_string().contains(\"expect `CREATE TABLE` or `CREATE SOURCE`\") => {\n        // log the statement kind and skip purification\n    }\n    r => r?,\n}","preventionTips":["Only pass CREATE TABLE / CREATE SOURCE SQL into purification helpers","Validate persisted table-definition SQL after migrations or manual edits","Add an AST-kind assertion at call sites that produce the SQL"],"tags":["sql","ddl","ast","catalog"],"backgroundTag":"invalid-argument-value","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}