cube-js/cube · error

Unexpected logical plan node: {:?}

Error message

Unexpected logical plan node: {:?}

What it means

Internal compiler error in cubesql's to_logical_plan converter: the egreedy/egg logical-plan expression tree contained a LogicalPlanLanguage node the converter has no arm for at this match position, so it cannot be lowered into a DataFusion LogicalPlan. This indicates an unhandled node kind in the Rust SQL planner rewrite layer, typically hit by an unsupported query shape.

Source

Thrown at rust/cubesql/cubesql/src/compile/rewrite/converter.rs:2466

                };

                LogicalPlan::Union(Union {
                    inputs,
                    schema: Arc::new(schema),
                    alias,
                })
            }
            LogicalPlanLanguage::Distinct(params) => {
                let input = Arc::new(self.to_logical_plan(params[0])?);

                LogicalPlan::Distinct(Distinct { input })
            }
            LogicalPlanLanguage::Values(values) => {
                let values = match_data_node!(node_by_id, values[0], ValuesValues);

                LogicalPlanBuilder::values(values)?.build()?
            }
            x => panic!("Unexpected logical plan node: {:?}", x),
        })
    }

    fn have_ungrouped_cube_scan_inside(node: &LogicalPlan) -> bool {
        match node {
            LogicalPlan::Projection(Projection { input, .. })
            | LogicalPlan::Filter(Filter { input, .. })
            | LogicalPlan::Window(Window { input, .. })
            | LogicalPlan::Aggregate(Aggregate { input, .. })
            | LogicalPlan::Sort(Sort { input, .. })
            | LogicalPlan::Repartition(Repartition { input, .. })
            | LogicalPlan::Limit(Limit { input, .. }) => {
                Self::have_ungrouped_cube_scan_inside(input)
            }
            LogicalPlan::Join(Join { left, right, .. })
            | LogicalPlan::CrossJoin(CrossJoin { left, right, .. }) => {
                Self::have_ungrouped_cube_scan_inside(left)
                    || Self::have_ungrouped_cube_scan_inside(right)

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Rewrite the query with more common constructs (e.g. UNION ALL, inline literals instead of VALUES)
  2. Upgrade CubeSQL so the node is handled
  3. Report the printed node variant to the Cube team to add a converter arm

Example fix

// before
SELECT * FROM (VALUES (1),(2)) t(x)
// after
SELECT 1 AS x UNION ALL SELECT 2;
Defensive patterns

Strategy: try-catch

Try / catch

let res = std::panic::catch_unwind(AssertUnwindSafe(|| planner.plan(sql)));
match res {
    Ok(p) => p,
    Err(_) => fallback_to_legacy_planner_or_return_unsupported(sql),
}

Prevention

When it happens

Trigger: A query compiles to a LogicalPlanLanguage variant not handled in the match — e.g. unusual set operations, nested VALUES, or new IR nodes added upstream but not to this converter.

Common situations: Queries using rarely supported SQL features (INTERSECT/EXCEPT variants, nested VALUES clauses) through the SQL API; version skew between compiler components.

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/c97ba1bcdfc28dae. Report an issue: GitHub.