risingwavelabs/risingwave · error
internal error: entered unreachable code
Error message
internal error: entered unreachable code
What it means
`NoShareNode` is a placeholder type used for plan conventions that do not support sharing (Common Subplan Elimination). Its `share_id` is `unreachable!()`: calling it panics with "internal error: entered unreachable code". It means code asked a convention that has no share support for a share id, which should be impossible if the optimizer only queries share_id on share-capable conventions.
Source
Thrown at src/frontend/src/optimizer/plan_node/mod.rs:89
type PlanNodeType;
fn as_share(plan: &Self::PlanRefDyn) -> Option<&Self::ShareNode>;
}
pub trait ShareNode<C: ConventionMarker>:
AnyPlanNodeMeta<C> + PlanTreeNodeUnary<C> + 'static
{
fn share_id(&self) -> ShareId;
fn new_share(share: generic::Share<PlanRef<C>>) -> PlanRef<C>;
fn replace_input(&self, plan: PlanRef<C>) -> PlanRef<C>;
fn fork_with_input(&self, plan: PlanRef<C>) -> PlanRef<C>;
}
pub struct NoShareNode<C: ConventionMarker>(!, PhantomData<C>);
impl<C: ConventionMarker> ShareNode<C> for NoShareNode<C> {
fn share_id(&self) -> ShareId {
unreachable!()
}
fn new_share(_plan: generic::Share<PlanRef<C>>) -> PlanRef<C> {
unreachable!()
}
fn replace_input(&self, _plan: PlanRef<C>) -> PlanRef<C> {
unreachable!()
}
fn fork_with_input(&self, _plan: PlanRef<C>) -> PlanRef<C> {
unreachable!()
}
}
impl<C: ConventionMarker> PlanTreeNodeUnary<C> for NoShareNode<C> {
fn input(&self) -> PlanRef<C> {
unreachable!()View on GitHub (pinned to 6469eb736d)
Solutions
- Only call `share_id()` on nodes/conventions where the ShareNode trait is implemented by a real share type, not NoShareNode.
- Gate share-specific optimizer logic behind a capability check or trait bound that excludes NoShareNode conventions.
- If you need sharing for a new convention, implement a real ShareNode instead of using NoShareNode.
Example fix
// before
let id = plan.share_id();
// after
if let Some(share) = plan.as_logical_share() {
let id = share.share_id();
} Defensive patterns
Strategy: type-guard
Validate before calling
// Rust: only query share_id on share-capable conventions
if plan.as_logical_share().is_some() { /* safe to call share_id */ } Type guard
fn has_share_support<C: ConventionMarker>(_p: &PlanRef<C>) -> bool { !std::any::TypeId::of::<C::ShareNode>().implements::<NoShareNode>() /* or a capability const */ } Try / catch
// Rust panics abort the thread; avoid by gating calls.
if let Some(share) = plan.as_logical_share() { let id = share.share_id(); } Prevention
- Gate share-specific logic behind convention capability checks.
- Add compile-time markers distinguishing share-capable conventions.
- Review generic passes that touch share_id for NoShareNode coverage.
When it happens
Trigger: Invoking `share_id()` on a `PlanRef` whose convention resolves to `NoShareNode` (e.g. batch or other non-share conventions); generic optimizer code that unconditionally calls `share_id` without checking that the convention supports shares.
Common situations: Adding a generic pass that iterates all plan nodes and calls share_id; incorrectly wiring a convention's ShareNode impl to NoShareNode; refactoring conventions and forgetting to gate share-specific logic.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- BatchPosixFsReader should not hit this branch. refer to `bat
- internal error: entered unreachable code
- shared node should be handled specially in PlanRef::clone_wi
- TableFunction should be converted to ProjectSet
- update should always be converted to batch plan
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/14a3583c890da0b0.
Report an issue: GitHub.