risingwavelabs/risingwave · error
ALTER SOURCE_RATE_LIMIT is not for table without source
Error message
ALTER SOURCE_RATE_LIMIT is not for table without source
What it means
`ALTER TABLE ... SOURCE_RATE_LIMIT` throttles the ingestion source associated with a table. When the target table is a plain table (e.g. a dml-target or regular table) with no associated source (associated_source_id is None), there is no source to throttle, so the handler bails. Only tables created from a connector (WITH a source / created via CREATE TABLE ... FROM ...) have an associated source.
Solutions
- Use `ALTER TABLE t DML_RATE_LIMIT ...` to throttle writes to a source-less table.
- Only apply SOURCE_RATE_LIMIT to tables created from an external source (e.g. Kafka/CDC-backed tables with an associated source).
- Create the table with a backing source if source-side throttling is actually the goal.
Example fix
// before ALTER TABLE plain_table SOURCE_RATE_LIMIT 100; // after ALTER TABLE plain_table DML_RATE_LIMIT 100; -- or, for a connector-backed table: ALTER TABLE kafka_backed_table SOURCE_RATE_LIMIT 100;
Defensive patterns
Strategy: validation
Validate before calling
-- Only apply SOURCE_RATE_LIMIT to tables backed by a source: SELECT t.name, s.id AS source_id FROM rw_catalog.rw_tables t LEFT JOIN rw_catalog.rw_sources s ON t.associated_source_id = s.id WHERE t.name = 'my_table' AND t.table_type = 'table'; -- If source_id IS NULL, use DML_RATE_LIMIT instead.
Prevention
- Remember SOURCE_RATE_LIMIT requires a connector-backed table; source-less tables need DML_RATE_LIMIT.
- Check associated_source_id (or the CREATE TABLE ... FROM ... definition) before altering.
- Keep rate-limit scripts keyed on throttle type + target semantics, not a single blanket ALTER.
When it happens
Trigger: Running `ALTER TABLE t SOURCE_RATE_LIMIT ...` where t exists and is a TABLE, but t.associated_source_id is None — i.e. a native RisingWave table not backed by an external source.
Common situations: Confusing DML rate limit (throttle_type=Dml, which works on any table) with the source rate limit (throttle_type=Source, which requires a connector-backed table); applying a source limit to a table populated only by DML/INSERT.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- ALTER SINK_RATE_LIMIT is not for sink into table
- ALTER TABLE SET SOURCE RATE LIMIT is not supported for…
- backfill order strategy
- Catalog error
- catalog error
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/73fa69e2814b4aed.
Report an issue: GitHub.
Appendix: source
Thrown at src/frontend/src/handler/alter_streaming_rate_limit.rs:96
let (source, schema_name) =
reader.get_source_by_name(db_name, schema_path, &real_table_name)?;
session.check_privilege_for_drop_alter(schema_name, &**source)?;
(StatementType::ALTER_SOURCE, source.id.as_raw_id())
}
(PbThrottleTarget::Table, PbThrottleType::Dml) => {
let reader = session.env().catalog_reader().read_guard();
let table =
check_table_mismatch(&reader, &session, db_name, schema_path, &real_table_name)?;
(StatementType::ALTER_TABLE, table.id.as_raw_id())
}
(PbThrottleTarget::Table, PbThrottleType::Source) => {
let reader = session.env().catalog_reader().read_guard();
let table =
check_table_mismatch(&reader, &session, db_name, schema_path, &real_table_name)?;
let source_id = if let Some(id) = table.associated_source_id {
id.as_raw_id()
} else {
bail!("ALTER SOURCE_RATE_LIMIT is not for table without source")
};
(StatementType::ALTER_TABLE, source_id)
}
(PbThrottleTarget::Table, PbThrottleType::Backfill) => {
let reader = session.env().catalog_reader().read_guard();
let table =
check_table_mismatch(&reader, &session, db_name, schema_path, &real_table_name)?;
if table.cdc_table_type.is_none() {
return Err(ErrorCode::InvalidInputSyntax(format!(
"\"{table_name}\" is not a CDC table",
))
.into());
}
(StatementType::ALTER_TABLE, table.id.as_raw_id())
}
(PbThrottleTarget::Sink, PbThrottleType::Sink) => {
let reader = session.env().catalog_reader().read_guard();
let (sink, schema_name) =View on GitHub (pinned to 6469eb736d)