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

  1. Reconnect with a properly working MySQL client/driver and correct credentials.
  2. Check proxy configs (e.g. connection poolers) that may skip or replay handshake steps.
  3. Patch to propagate an error instead of panicking: return early / send ERR packet when user is None.
  4. 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

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


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)