risingwavelabs/risingwave · error · SinkError::Coordinator
Invalid schema change operation
Error message
Invalid schema change operation
What it means
`commit_schema_change` handles sink schema evolution; the protobuf `PbSinkSchemaChange` must carry an `op`. When `schema_change.op` is None, the committer cannot interpret the change and returns this Coordinator error.
Source
Thrown at src/connector/src/sink/snowflake_redshift/snowflake.rs:792
client.execute_create_pipe().await?;
client.execute_create_merge_into_task().await?;
}
Ok(())
}
async fn commit_data(&mut self, _epoch: u64, _metadata: Vec<SinkMetadata>) -> Result<()> {
Ok(())
}
async fn commit_schema_change(
&mut self,
_epoch: u64,
schema_change: PbSinkSchemaChange,
) -> Result<()> {
use risingwave_pb::stream_plan::sink_schema_change::PbOp as SinkSchemaChangeOp;
let schema_change_op = schema_change
.op
.ok_or_else(|| SinkError::Coordinator(anyhow!("Invalid schema change operation")))?;
let SinkSchemaChangeOp::AddColumns(add_columns) = schema_change_op else {
return Err(SinkError::Coordinator(anyhow!(
"Only AddColumns schema change is supported for Snowflake sink"
)));
};
let client = self.client.as_mut().ok_or_else(|| {
SinkError::Config(anyhow!("Snowflake sink committer is not initialized."))
})?;
client
.execute_alter_add_columns(
&add_columns
.fields
.into_iter()
.map(|f| {
let dt = DataType::from(f.data_type.unwrap());
Ok((f.name, convert_snowflake_data_type(&dt)?))
})
.collect::<Result<Vec<_>>>()?,View on GitHub (pinned to 6469eb736d)
Solutions
- Ensure the component producing `SinkSchemaChange` sets a valid `op` (currently only AddColumns)
- Upgrade meta/frontend so schema changes are built with the op populated
- If the event is corrupt, recreate the sink rather than retrying the same event
Example fix
// before
let change = PbSinkSchemaChange { op: None, ..Default::default() };
// after
let change = PbSinkSchemaChange {
op: Some(PbOp::AddColumns(PbAddColumns { fields: new_fields })),
..Default::default()
}; Defensive patterns
Strategy: try-catch
Validate before calling
if schema_change.op.is_none() {
return Err("schema change has no op set");
} Type guard
fn has_op(c: &PbSinkSchemaChange) -> bool { c.op.is_some() } Try / catch
match sink.commit_schema_change(epoch, change).await {
Err(e) if e.to_string().contains("Invalid schema change") => {
log::warn!("dropping corrupt schema change: {e}");
}
r => r?,
} Prevention
- Always construct SinkSchemaChange with an explicit op
- Keep meta/frontend and connector versions aligned
When it happens
Trigger: Calling `commit_schema_change` with a `PbSinkSchemaChange` message whose `op` field was never set (an empty/invalid schema change from the stream plan or meta coordinator).
Common situations: Meta node emitting a schema-change event with no op set due to a bug or partial protobuf construction; manually replaying messages; version skew between frontend/meta producing old pb messages.
Related errors
- Invalid schema change operation
- Only AddColumns schema change is supported for Snowflake sin
- Snowflake sink committer is not initialized.
- feature {feature:?} is not available based on your license
- {e}
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/685d7b548d4d5685.
Report an issue: GitHub.