risingwavelabs/risingwave · error · SinkError
only iceberg table can be altered as sink
Error message
only iceberg table can be altered as sink
What it means
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)`.
Source
Thrown at src/meta/src/controller/streaming_job.rs:3217
.find_also_related(Object)
.one(&txn)
.await?
.ok_or_else(|| MetaError::catalog_id_not_found(ObjectType::Sink.as_str(), sink_id))?;
validate_sink_props(&sink, &props)?;
let definition = sink.definition.clone();
let [mut stmt]: [_; 1] = Parser::parse_sql(&definition)
.map_err(|e| SinkError::Config(anyhow!(e)))?
.try_into()
.unwrap();
if let Statement::CreateTable {
with_options,
engine,
..
} = &mut stmt
{
if !matches!(engine, Engine::Iceberg) {
return Err(SinkError::Config(anyhow!(
"only iceberg table can be altered as sink"
))
.into());
}
update_stmt_with_props(with_options, &props)?;
} else {
panic!("definition is not a create iceberg table statement")
}
let mut new_config = sink.properties.clone().into_inner();
new_config.extend(props.clone());
let definition = stmt.to_string();
let active_sink = sink::ActiveModel {
sink_id: Set(sink_id),
properties: Set(risingwave_meta_model::Property(new_config.clone())),
definition: Set(definition.clone()),
..Default::default()
};View on GitHub (pinned to 6469eb736d)
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.
Example fix
-- before: ALTER on a non-iceberg table ALTER TABLE t ALTER CONNECTOR PROPS (...); -- errors -- after: only iceberg tables ALTER TABLE iceberg_t WITH (SINK ...) ENGINE = ICEBERG; -- then alter its props
Defensive patterns
Strategy: validation
Validate before calling
-- ensure the table is an iceberg table before altering as sink SELECT engine FROM rw_tables WHERE name = 'my_table'; -- must be 'iceberg'
Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- order_key must not be empty
- System column `{}` is not allowed in order_key
- sink with auto schema change should have only 1 fragment, bu
- No allow_alter_on_fly fields registered for sink: {sink_name
- Field '{field}' is not allowed to be altered on the fly for
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/d7df96a37e810772.
Report an issue: GitHub.