risingwavelabs/risingwave · error · anyhow::Error
no state table id in sink: {}
Error message
no state table id in sink: {} What it means
When a committed-epoch subscriber is created for a sink, the meta node looks up the sink's state table IDs and requires at least one to subscribe its committed epoch in Hummock. A sink with no state table cannot be coordinated for commit epochs, so the subscriber task returns this error and the sink coordination fails to start.
Source
Thrown at src/meta/src/manager/sink_coordination/manager.rs:90
#[derive(Clone)]
pub struct SinkCoordinatorManager {
request_tx: mpsc::Sender<ManagerRequest>,
}
fn new_committed_epoch_subscriber(
hummock_manager: HummockManagerRef,
metadata_manager: MetadataManager,
) -> SinkCommittedEpochSubscriber {
Arc::new(move |sink_id| {
let hummock_manager = hummock_manager.clone();
let metadata_manager = metadata_manager.clone();
async move {
let state_table_ids = metadata_manager
.get_sink_state_table_ids(sink_id)
.await
.map_err(SinkError::from)?;
let Some(table_id) = state_table_ids.first() else {
return Err(anyhow!("no state table id in sink: {}", sink_id).into());
};
hummock_manager
.subscribe_table_committed_epoch(*table_id)
.await
.map_err(SinkError::from)
}
.boxed()
})
}
impl SinkCoordinatorManager {
pub fn start_worker(
db: DatabaseConnection,
hummock_manager: HummockManagerRef,
metadata_manager: MetadataManager,
iceberg_compact_stat_sender: UnboundedSender<IcebergSinkCompactionUpdate>,
await_tree_reg: await_tree::Registry,
) -> (Self, (JoinHandle<()>, Sender<()>)) {View on GitHub (pinned to 6469eb736d)
Solutions
- Inspect the sink catalog (`rw_catalog.rw_sinks` / meta metadata) to confirm the sink has an associated state (internal) table; recreate the sink if the state table is missing.
- If the sink id belongs to a dropped sink, guard against coordinating already-removed sinks and clean up stale coordination state.
- Ensure DDL completes atomically — re-run the sink creation if a previous `CREATE SINK` failed midway.
- Upgrade if migrating from a version where some sink types had no state table.
Example fix
// before
let Some(table_id) = state_table_ids.first() else {
return Err(anyhow!("no state table id in sink: {}", sink_id).into());
};
// after
let Some(table_id) = state_table_ids.first() else {
return Err(SinkError::from(anyhow!(
"no state table id in sink: {}; sink may be corrupted or dropped, recreate the sink",
sink_id
)));
}; Defensive patterns
Strategy: validation
Validate before calling
// Before starting sink coordination, verify the sink has a state table
let state_table_ids = metadata_manager.get_sink_state_table_ids(sink_id).await?;
if state_table_ids.is_empty() {
return Err(anyhow!("sink {} has no state table; recreate the sink", sink_id));
} Try / catch
match new_committed_epoch_subscriber(sink_id).await {
Err(e) if e.to_string().contains("no state table id") => {
tracing::error!("sink {} is missing its state table; check catalog or recreate", sink_id);
}
other => { /* normal handling */ }
} Prevention
- Verify CREATE SINK completed fully before starting coordination
- Clean up coordination state for dropped sinks
- Check the catalog for internal tables after failed DDL or migrations
When it happens
Trigger: `start_worker` spawns `new_committed_epoch_subscriber`; `get_sink_state_table_ids(sink_id)` returns an empty list for the given sink id.
Common situations: Sink created without a state table (corrupt/incomplete catalog state, e.g. interrupted DDL or migration from an older format); querying a sink id that was dropped concurrently; append-only sinks of a legacy version that lacked state tables.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- state table {} is not registered to hummock
- job {} in database {} has no state table after recovery
- replacement sink catalog requires a sink job
- object {} is not a sink
- SinkError::Config(anyhow!(e))
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/ff7a4f343440e93e.
Report an issue: GitHub.