cube-js/cube · error
This query doesnt have a plan, because it already has values
Error message
This query doesnt have a plan, because it already has values for response
What it means
CubeSQL's as_physical_plan() panics when the QueryPlan is a terminal/meta variant (MetaOk, MetaTabular, CopyFrom, CreateEmptyTempTable). These plans carry their response values directly and never produce a physical execution plan.
Source
Thrown at rust/cubesql/cubesql/src/compile/plan.rs:141
pub fn as_logical_plan(&self) -> LogicalPlan {
self.try_as_logical_plan().cloned().unwrap()
}
pub async fn as_physical_plan(&self) -> Result<Arc<dyn ExecutionPlan>, CubeError> {
match self {
QueryPlan::DataFusionSelect(plan, ctx)
| QueryPlan::CreateTempTable(plan, ctx, _, _, _) => {
DataFrame::new(ctx.state.clone(), plan)
.create_physical_plan()
.await
.map_err(|e| CubeError::from(e))
}
QueryPlan::MetaOk(_, _)
| QueryPlan::MetaTabular(_, _)
| QueryPlan::CopyFrom(_)
| QueryPlan::CreateEmptyTempTable(_) => {
panic!("This query doesnt have a plan, because it already has values for response")
}
}
}
pub fn print(&self, pretty: bool) -> Result<String, CubeError> {
match self {
QueryPlan::DataFusionSelect(plan, _) | QueryPlan::CreateTempTable(plan, _, _, _, _) => {
if pretty {
Ok(plan.display_indent().to_string())
} else {
Ok(plan.display().to_string())
}
}
QueryPlan::MetaOk(_, _)
| QueryPlan::MetaTabular(_, _)
| QueryPlan::CopyFrom(_)
| QueryPlan::CreateEmptyTempTable(_) => Ok(
"This query doesnt have a plan, because it already has values for response"View on GitHub (pinned to 7d981676b3)
Solutions
- Check the QueryPlan variant before calling as_physical_plan and handle MetaOk/MetaTabular/CopyFrom/CreateEmptyTempTable by extracting their values directly.
- Route meta queries through the response-returning path instead of physical planning.
- File/inspect upstream: this panic usually indicates a planner routing bug in cubesql.
Example fix
// before
let physical = plan.as_physical_plan()?;
// after
let physical = match plan {
QueryPlan::MetaOk(..) | QueryPlan::MetaTabular(..) => return Ok(plan_response(plan)),
_ => plan.as_physical_plan()?,
}; Defensive patterns
Strategy: type-guard
Type guard
fn is_plan_executable(plan: &QueryPlan) -> bool {
!matches!(plan,
QueryPlan::MetaOk(_, _)
| QueryPlan::MetaTabular(_, _)
| QueryPlan::CopyFrom(_)
| QueryPlan::CreateEmptyTempTable(_))
} Try / catch
// panic!, not Result — cannot catch in Rust; guard before calling
if is_plan_executable(&plan) {
let physical = plan.as_physical_plan()?;
} else {
return handle_meta_response(plan);
} Prevention
- Handle meta/copy plans on their dedicated response path
- Add variant checks before physical planning
- Cover meta query routing with tests
When it happens
Trigger: Calling as_physical_plan() on a QueryPlan that already holds final response values (meta queries, COPY FROM, create-empty-temp-table) instead of a real query plan.
Common situations: Planner bugs where a meta-response plan reaches the physical planning stage; custom SQL proxy code misinterpreting plan variants; queries like COPY FROM routed through the normal plan path.
Related errors
- Should be rewritten with UtcTimestamp function
- CreateExternalTable is not supported
- Explain is not supported
- Analyze is not supported
- Unsupported extension node: {}
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/134a341f763f99d4.
Report an issue: GitHub.