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

  1. Upgrade Databend to a version whose refresh hook covers the new object kind
  2. Identify the object triggering the refresh (query log / hook registration) and remove or re-create it with a supported kind
  3. As a code fix, replace the `_ => unreachable!()` arm with a logged no-op or returned internal error naming the unhandled variant
  4. 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

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


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)