risingwavelabs/risingwave · error · SinkError::Coordinator
Schema change is not implemented for two-phase commit coordi
Error message
Schema change is not implemented for two-phase commit coordinator {} What it means
Identical to the single-phase variant but on the two-phase commit coordinator trait: the default `commit_schema_change` implementation always returns this error, meaning the sink connector does not support committing schema evolution during the two-phase commit protocol.
Source
Thrown at src/connector/src/sink/mod.rs:1005
/// Return serialized commit metadata to be passed to `commit`.
async fn pre_commit(
&mut self,
epoch: u64,
metadata: Vec<SinkMetadata>,
schema_change: Option<PbSinkSchemaChange>,
) -> Result<Option<Vec<u8>>>;
/// Idempotent implementation is required, because `commit_data` in the same epoch could be called multiple times.
async fn commit_data(&mut self, epoch: u64, commit_metadata: Vec<u8>) -> Result<()>;
/// Idempotent implementation is required, because `commit_schema_change` in the same epoch could be called multiple
/// times.
async fn commit_schema_change(
&mut self,
_epoch: u64,
_schema_change: PbSinkSchemaChange,
) -> Result<()> {
Err(SinkError::Coordinator(anyhow!(
"Schema change is not implemented for two-phase commit coordinator {}",
std::any::type_name::<Self>()
)))
}
/// Idempotent implementation is required, because `abort` in the same epoch could be called multiple times.
async fn abort(&mut self, epoch: u64, commit_metadata: Vec<u8>);
}
impl SinkImpl {
pub fn new(mut param: SinkParam) -> Result<Self> {
const PRIVATE_LINK_TARGET_KEY: &str = "privatelink.targets";
// remove privatelink related properties if any
param.properties.remove(PRIVATE_LINK_TARGET_KEY);
let sink_type = param
.propertiesView on GitHub (pinned to 6469eb736d)
Solutions
- Defer schema changes until the sink is recreated with the new schema
- Switch to a sink connector that implements schema-change commit in its two-phase coordinator
- Implement `commit_schema_change` in the connector's coordinator if you own the connector
Defensive patterns
Strategy: try-catch
Try / catch
match err {
SinkError::Coordinator(e) if e.to_string().contains("two-phase commit coordinator") => {
// handle: pause sink, recreate with new schema, resume
}
e => return Err(e.into()),
} Prevention
- Restrict ALTERs on sources feeding decoupled sinks to connectors with schema-change commit implemented
- Test schema evolution on a staging sink before applying in production
When it happens
Trigger: A `PbSinkSchemaChange` is committed at an epoch against a two-phase commit coordinator (sink decouple enabled) whose type only provides the default `commit_schema_change`, i.e. any connector that has not overridden it (typically triggered by upstream schema alterations).
Common situations: Running an ALTER on the source/mv feeding an Iceberg-style decoupled sink with a connector lacking schema evolution; misjudging which connectors support schema-change commit.
Related errors
- LanceDB sink does not support schema change
- LanceDB pre-commit epoch {} does not match commit epoch {}
- LanceDB pre-commit sink id {} does not match coordinator sin
- Schema change is not implemented for single-phase commit coo
- (dynamic: channel send error on shutdown signal)
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/282fae1a9a08f9f6.
Report an issue: GitHub.