risingwavelabs/risingwave · error
not implemented: DECLARE SUBSCRIPTION CURSOR
Error message
not implemented: DECLARE SUBSCRIPTION CURSOR
What it means
`unimplemented!()` fires in `Planner::plan_statement` (src/frontend/src/planner/statement.rs:28) when a `DECLARE SUBSCRIPTION CURSOR` statement reaches the planner. The frontend binds the statement but the planner has no implementation for planning subscription cursors, so it panics deliberately to mark the feature as not yet supported.
Solutions
- Avoid `DECLARE SUBSCRIPTION CURSOR`; use a regular `DECLARE ... CURSOR` on a query, or consume subscriptions via `SUBSCRIBE` output streams.
- Upgrade RisingWave if a newer version added subscription cursor support.
- If you need the feature, file/implement a planner arm returning a proper plan or a user-facing 'not supported' error instead of `unimplemented!()`.
Example fix
// before
BoundStatement::DeclareSubscriptionCursor(_) => unimplemented!(),
// after
BoundStatement::DeclareSubscriptionCursor(_) => {
Err(ErrorCode::NotImplemented(
"DECLARE SUBSCRIPTION CURSOR is not supported".into(),
1191.into(),
).into())
} Defensive patterns
Strategy: validation
Validate before calling
// Reject subscription cursor statements before sending
if /^DECLARE\s+\w+\s+SUBSCRIPTION\s+CURSOR/i.test(stmt) {
throw new Error('DECLARE SUBSCRIPTION CURSOR is not supported; use SUBSCRIBE or a regular cursor');
} Try / catch
// Panics are not catchable in SQL; guard the statement text client-side
if (stmt.toLowerCase().includes('subscription cursor')) {
return Promise.reject(new Error('unsupported statement: DECLARE SUBSCRIPTION CURSOR'));
} Prevention
- Do not port Postgres subscription-cursor syntax to RisingWave.
- Use SUBSCRIBE to consume subscription changelogs.
- Check the RisingWave feature matrix before using new SQL syntax.
When it happens
Trigger: Executing `DECLARE sub_cursor SUBSCRIPTION CURSOR FOR ...` (subscription cursor variant of DECLARE) against the frontend. Ordinary `DECLARE ... CURSOR FOR <query>` works; only the subscription-cursor form hits this arm.
Common situations: Porting Postgres application code that uses subscription cursors, or testing new streaming subscription features before frontend planning support landed.
Related errors
- not implemented: FETCH
- unimplemented
- call predicate_pushdown of the PlanRef instead of calling…
- call prune_col of the PlanRef instead of calling directly…
- children expression must not be empty for constant lookup…
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/45c8c7854ea57514.
Report an issue: GitHub.
Appendix: source
Thrown at src/frontend/src/planner/statement.rs:28
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::binder::BoundStatement;
use crate::error::Result;
use crate::optimizer::LogicalPlanRoot;
use crate::planner::Planner;
impl Planner {
pub(super) fn plan_statement(&mut self, stmt: BoundStatement) -> Result<LogicalPlanRoot> {
match stmt {
BoundStatement::Insert(i) => self.plan_insert(*i),
BoundStatement::Delete(d) => self.plan_delete(*d),
BoundStatement::Update(u) => self.plan_update(*u),
BoundStatement::Query(q) => self.plan_query(*q),
BoundStatement::DeclareCursor(d) => self.plan_query(*d.query),
BoundStatement::DeclareSubscriptionCursor(_) => unimplemented!(),
BoundStatement::FetchCursor(_) => unimplemented!(),
BoundStatement::CreateView(c) => self.plan_query(*c.query),
}
}
}
View on GitHub (pinned to 6469eb736d)