databendlabs/databend · error
mysql handler should be authed when call
Error message
mysql handler should be authed when call
What it means
start_keep_alive in the MySQL interactive worker reads the authenticated user from the session with get_current_user().expect(...). The invariant is that keep-alive only starts after authentication succeeded, so current user must exist. The panic fires when the worker reaches start_keep_alive without a completed auth — an auth state-machine violation.
Solutions
- Reconnect with a properly working MySQL client/driver and correct credentials.
- Check proxy configs (e.g. connection poolers) that may skip or replay handshake steps.
- Patch to propagate an error instead of panicking: return early / send ERR packet when user is None.
- Capture version and stack trace and report; indicates an auth lifecycle bug.
Example fix
// before
let user_name = session.get_current_user().expect("mysql handler should be authed when call").name;
// after
let user_name = match session.get_current_user() {
Some(u) => u.name,
None => { self.kill(); return; }
}; Defensive patterns
Strategy: try-catch
Validate before calling
// client: ensure handshake completed before sending queries if (!connection.is_authenticated()) await connection.completeHandshake();
Type guard
fn is_authed(session: &Session) -> bool { session.get_current_user().is_some() } Try / catch
if let Some(user) = session.get_current_user() { /* start keep alive */ } else { /* abort worker gracefully */ } Prevention
- Use MySQL clients that complete the auth handshake before COM_QUERY
- Check connection poolers don't replay partial handshakes
- Keep databend-query updated for auth lifecycle fixes
- Return an ERR packet instead of panicking in worker code
When it happens
Trigger: on_query invoked before the MySQL handshake/auth phase completed; auth succeeded but the user was cleared from the session; internal misordering of worker lifecycle callbacks.
Common situations: Client connecting with broken auth flow (e.g. auth plugin negotiation failing partially) yet issuing a query; proxy/connector sending COM_QUERY before handshake finish; version-specific regression in session user management.
Related errors
- login_handler expect session id in ctx
- Temp table id used up
- {}
- Invalid temp table desc
- expect tuple type
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/5366339ba798935a.
Report an issue: GitHub.
Appendix: source
Thrown at src/query/service/src/servers/mysql/mysql_interactive_worker.rs:604
salt: [u8; 20],
keep_alive_task: KeepAliveTask,
) -> InteractiveWorker {
InteractiveWorker {
version: format!("{MYSQL_VERSION}-{}", version.commit_detail),
base: InteractiveWorkerBase { session, version },
salt,
client_addr,
keep_alive_task,
}
}
fn start_keep_alive(&mut self) {
let session = &self.base.session;
let tenant = session.get_current_tenant();
let session_id = session.get_id();
let user_name = session
.get_current_user()
.expect("mysql handler should be authed when call")
.name;
let (shutdown_tx, mut shutdown_rx) = oneshot::channel();
let task = databend_common_base::runtime::spawn(async move {
loop {
UserApiProvider::instance()
.client_session_api(&tenant)
.upsert_client_session_id(
&user_name,
&session_id,
Duration::from_secs(3600 + 600),
)
.await
.ok();
tokio::select! {
_ = tokio::time::sleep(Duration::from_secs(3600)) => {},
_ = &mut shutdown_rx => break,
}View on GitHub (pinned to 288d84d76e)