databendlabs/databend · error
internal error: entered unreachable code
Error message
internal error: entered unreachable code
What it means
do_refresh (src/query/service/src/interpreters/hook/refresh_hook.rs:162) spawns refresh tasks for stream/table objects; the match on the hook's target kind expects only the handled variants and panics via `_ => unreachable!()` for anything else. 'internal error: entered unreachable code' means a refresh hook received a target object kind it was not designed to handle.
Solutions
- Upgrade Databend to a version whose refresh hook covers the new object kind
- Identify the object triggering the refresh (query log / hook registration) and remove or re-create it with a supported kind
- As a code fix, replace the `_ => unreachable!()` arm with a logged no-op or returned internal error naming the unhandled variant
- File a bug with the object type and Databend version
Example fix
// before
_ => unreachable!(),
// after
other => {
return Err(ErrorCode::Internal(format!(
"refresh hook: unhandled target variant {:?}", other
)));
} Defensive patterns
Strategy: retry
Validate before calling
// before registering/refreshing, check the object kind is one the hook supports
let kind = table.get_table_info().engine();
if !SUPPORTED_REFRESH_ENGINES.contains(&kind.as_str()) {
return Ok(()); // skip refresh for unsupported kinds
} Type guard
if let HookTarget::Stream(_) | HookTarget::MaterializedView(_) = target { /* handled */ } else { /* skip or log */ } Try / catch
// wrap refresh task spawn so one bad object doesn't kill the loop
for obj in objects {
if let Err(e) = do_refresh(obj).await {
log::warn!("skip refresh for {:?}: {}", obj, e);
}
} Prevention
- Only create streams/views with engines known to support refresh hooks
- After upgrading, re-create streams built on exotic engines
- Monitor query-node logs for refresh-hook warnings to catch unsupported objects early
When it happens
Trigger: execute_refresh_hook runs do_refresh for a hook whose matched object/plan variant falls into the catch-all arm — e.g. a refresh triggered on a table kind or plan variant added later that the hook's match statement does not enumerate.
Common situations: Background refresh of streams/materialized views after an upgrade introduced a new object kind; environments with unusual table engines registered where the refresh hook's match was not extended.
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
- logic error: expected CreateTable plan
- internal error: entered unreachable code
- table name is provided
- Input plan must be Query, but it's
- Input plan must be Query, but it's
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/b162fd46370a6585.
Report an issue: GitHub.
Appendix: source
Thrown at src/query/service/src/interpreters/hook/refresh_hook.rs:162
hook_clear_m_cte_temp_table(&query_ctx)?;
hook_vacuum_temp_files(&query_ctx)?;
hook_disk_temp_dir(&query_ctx)?;
Ok(())
},
));
let mut pipelines = build_res.sources_pipelines;
pipelines.push(build_res.main_pipeline);
let complete_executor =
PipelineCompleteExecutor::from_pipelines(pipelines, settings)?;
ctx_cloned.set_executor(complete_executor.get_inner())?;
complete_executor.execute().await
} else {
Ok(())
}
}
_ => unreachable!(),
}
});
}
let _ = futures::future::try_join_all(tasks).await?;
Ok(())
}
async fn resolve_refresh_desc(
ctx: &Arc<QueryContext>,
mut desc: RefreshDesc,
) -> Result<Option<RefreshDesc>> {
let Some((database, table)) = resolve_current_table_name_by_id(
ctx,
"refresh",
&desc.catalog,
&desc.database,
&desc.table,View on GitHub (pinned to 288d84d76e)