{"record":{"id":"d7df96a37e810772","repo":"risingwavelabs/risingwave","slug":"only-iceberg-table-can-be-altered-as-sink","errorCode":null,"errorMessage":"only iceberg table can be altered as sink","messagePattern":"only iceberg table can be altered as sink","errorType":"validation","errorClass":"SinkError","httpStatus":null,"severity":"error","filePath":"src/meta/src/controller/streaming_job.rs","lineNumber":3217,"sourceCode":"            .find_also_related(Object)\n            .one(&txn)\n            .await?\n            .ok_or_else(|| MetaError::catalog_id_not_found(ObjectType::Sink.as_str(), sink_id))?;\n        validate_sink_props(&sink, &props)?;\n\n        let definition = sink.definition.clone();\n        let [mut stmt]: [_; 1] = Parser::parse_sql(&definition)\n            .map_err(|e| SinkError::Config(anyhow!(e)))?\n            .try_into()\n            .unwrap();\n        if let Statement::CreateTable {\n            with_options,\n            engine,\n            ..\n        } = &mut stmt\n        {\n            if !matches!(engine, Engine::Iceberg) {\n                return Err(SinkError::Config(anyhow!(\n                    \"only iceberg table can be altered as sink\"\n                ))\n                .into());\n            }\n            update_stmt_with_props(with_options, &props)?;\n        } else {\n            panic!(\"definition is not a create iceberg table statement\")\n        }\n        let mut new_config = sink.properties.clone().into_inner();\n        new_config.extend(props.clone());\n\n        let definition = stmt.to_string();\n        let active_sink = sink::ActiveModel {\n            sink_id: Set(sink_id),\n            properties: Set(risingwave_meta_model::Property(new_config.clone())),\n            definition: Set(definition.clone()),\n            ..Default::default()\n        };","sourceCodeStart":3199,"sourceCodeEnd":3235,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/controller/streaming_job.rs#L3199-L3235","documentation":"In `update_iceberg_table_props_by_table_id`, the definition is parsed and must be a `CREATE TABLE ... ENGINE = ICEBERG` statement (an iceberg table associated with a sink). If the parsed statement's engine is not Iceberg, the controller rejects the alter with `SinkError::Config(\"only iceberg table can be altered as sink\")`. This path only supports on-the-fly property changes for iceberg tables created via `CREATE TABLE ... WITH (SINK)`.","triggerScenarios":"Calling the iceberg-table property alter API (update_iceberg_table_props_by_table_id) against a table whose definition declares an engine other than Iceberg, or which is a regular non-iceberg table.","commonSituations":"Passing a table_id of a normal (non-iceberg) table to the iceberg alter endpoint; attempting to alter connector props on a table that was not created with `ENGINE = ICEBERG` / sink-to-iceberg; client-side routing that sends the wrong table id.","solutions":["Confirm the target table is an iceberg table created with `CREATE TABLE ... WITH (SINK ...) ENGINE = ICEBERG`.","Use the regular sink alter path (ALTER SINK) for non-iceberg sinks instead of the iceberg-table alter API.","Check that the sink_id/table_id pair passed in PbExtraOptions::AlterIcebergTableIds refers to the iceberg table's associated sink.","If you need iceberg semantics, recreate the table as an iceberg table."],"exampleFix":"-- before: ALTER on a non-iceberg table\nALTER TABLE t ALTER CONNECTOR PROPS (...); -- errors\n-- after: only iceberg tables\nALTER TABLE iceberg_t WITH (SINK ...) ENGINE = ICEBERG; -- then alter its props","handlingStrategy":"validation","validationCode":"-- ensure the table is an iceberg table before altering as sink\nSELECT engine FROM rw_tables WHERE name = 'my_table'; -- must be 'iceberg'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only call the iceberg-table alter API on tables created with ENGINE = ICEBERG and a SINK clause.","Route non-iceberg sinks to the regular ALTER SINK path.","Verify table_id/sink_id pairing in AlterIcebergTableIds before calling the API."],"tags":["sink","iceberg","meta","validation"],"backgroundTag":"unsupported-operation","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}