{"record":{"id":"73fa69e2814b4aed","repo":"risingwavelabs/risingwave","slug":"alter-source-rate-limit-is-not-for-table-without-s","errorCode":null,"errorMessage":"ALTER SOURCE_RATE_LIMIT is not for table without source","messagePattern":"ALTER SOURCE_RATE_LIMIT is not for table without source","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/frontend/src/handler/alter_streaming_rate_limit.rs","lineNumber":96,"sourceCode":"            let (source, schema_name) =\n                reader.get_source_by_name(db_name, schema_path, &real_table_name)?;\n            session.check_privilege_for_drop_alter(schema_name, &**source)?;\n            (StatementType::ALTER_SOURCE, source.id.as_raw_id())\n        }\n        (PbThrottleTarget::Table, PbThrottleType::Dml) => {\n            let reader = session.env().catalog_reader().read_guard();\n            let table =\n                check_table_mismatch(&reader, &session, db_name, schema_path, &real_table_name)?;\n            (StatementType::ALTER_TABLE, table.id.as_raw_id())\n        }\n        (PbThrottleTarget::Table, PbThrottleType::Source) => {\n            let reader = session.env().catalog_reader().read_guard();\n            let table =\n                check_table_mismatch(&reader, &session, db_name, schema_path, &real_table_name)?;\n            let source_id = if let Some(id) = table.associated_source_id {\n                id.as_raw_id()\n            } else {\n                bail!(\"ALTER SOURCE_RATE_LIMIT is not for table without source\")\n            };\n            (StatementType::ALTER_TABLE, source_id)\n        }\n        (PbThrottleTarget::Table, PbThrottleType::Backfill) => {\n            let reader = session.env().catalog_reader().read_guard();\n            let table =\n                check_table_mismatch(&reader, &session, db_name, schema_path, &real_table_name)?;\n            if table.cdc_table_type.is_none() {\n                return Err(ErrorCode::InvalidInputSyntax(format!(\n                    \"\\\"{table_name}\\\" is not a CDC table\",\n                ))\n                .into());\n            }\n            (StatementType::ALTER_TABLE, table.id.as_raw_id())\n        }\n        (PbThrottleTarget::Sink, PbThrottleType::Sink) => {\n            let reader = session.env().catalog_reader().read_guard();\n            let (sink, schema_name) =","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/frontend/src/handler/alter_streaming_rate_limit.rs#L78-L114","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nALTER TABLE plain_table SOURCE_RATE_LIMIT 100;\n// after\nALTER TABLE plain_table DML_RATE_LIMIT 100;\n-- or, for a connector-backed table:\nALTER TABLE kafka_backed_table SOURCE_RATE_LIMIT 100;","handlingStrategy":"validation","validationCode":"-- Only apply SOURCE_RATE_LIMIT to tables backed by a source:\nSELECT t.name, s.id AS source_id\nFROM rw_catalog.rw_tables t\nLEFT JOIN rw_catalog.rw_sources s ON t.associated_source_id = s.id\nWHERE t.name = 'my_table' AND t.table_type = 'table';\n-- If source_id IS NULL, use DML_RATE_LIMIT instead.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["risingwave","sql","rate-limit","invalid-target"],"backgroundTag":"invalid-argument-value","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}