{"record":{"id":"b357089d5dde68d8","repo":"databendlabs/databend","slug":"expect-query-info","errorCode":null,"errorMessage":"expect query info","messagePattern":"expect query info","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/query/service/src/servers/flight/v1/exchange/exchange_manager.rs","lineNumber":516,"sourceCode":"                };\n\n                return Ok(());\n            }\n        }\n\n        // do nothing\n        Ok(())\n    }\n\n    fn remove_if_leak_query(&self, query_id: String) {\n        let leak_query_id = {\n            let queries_coordinator_guard = self.queries_coordinator.lock();\n            let queries_coordinator = unsafe { &mut *queries_coordinator_guard.deref().get() };\n\n            match queries_coordinator.get(&query_id) {\n                None => None,\n                Some(may_leak_query) => {\n                    let info = may_leak_query.info.as_ref().expect(\"expect query info\");\n                    match info.started.load(Ordering::SeqCst) {\n                        true => None,\n                        false => Some(query_id),\n                    }\n                }\n            }\n        };\n\n        if let Some(query_id) = leak_query_id {\n            warn!(\n                \"Query {} cannot start command while in 180 seconds\",\n                query_id\n            );\n            self.on_finished_query(\n                &query_id,\n                Some(ErrorCode::Internal(format!(\n                    \"Query {} cannot start command while in 180 seconds\",\n                    query_id","sourceCodeStart":498,"sourceCodeEnd":534,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/query/service/src/servers/flight/v1/exchange/exchange_manager.rs#L498-L534","documentation":"`remove_if_leak_query` inspects a registered QueryCoordinator's `info` and panics with `expect(\"expect query info\")` if `info` is None. The invariant is that a coordinator stored in the map always carries QueryInfo; firing means the entry was inserted without info or info was taken/cleared concurrently.","triggerScenarios":"Leak-detection cleanup iterates `queries_coordinator` and finds an entry whose `info` was never set (registration raced with info assignment) or was already consumed, while `remove_if_leak_query` runs.","commonSituations":"A query failing/cancelling between coordinator registration and `set_ctx`/info assignment while the leak sweeper runs; manual insertion paths or version-skewed nodes sharing state.","solutions":["Check the logs for the query id and whether set_ctx/prepare_pipeline ran before the sweeper; fix any early-abort path that registers a coordinator without info.","Make the sweeper resilient: treat `info == None` as a leak candidate (or skip) instead of panicking.","Reduce the race window by assigning QueryInfo atomically with coordinator insertion.","Upgrade to a version where leak-sweep handling of uninitialized coordinators is hardened."],"exampleFix":"// before\nlet info = may_leak_query.info.as_ref().expect(\"expect query info\");\n// after\nlet Some(info) = may_leak_query.info.as_ref() else { return Some(query_id); };","handlingStrategy":"type-guard","validationCode":"// guard before inspecting leak candidates\nif may_leak_query.info.is_none() { /* treat as leak or skip */ }","typeGuard":"fn has_query_info(c: &QueryCoordinator) -> bool { c.info.is_some() }","tryCatchPattern":"// tolerate missing info in the sweeper\nlet Some(info) = may_leak_query.info.as_ref() else { return Some(query_id) };","preventionTips":["Set QueryInfo atomically with coordinator insertion","Avoid running leak sweeps while queries are mid-initialization","Log coordinator lifecycle events to trace init-order violations"],"tags":["rust","panic","query-lifecycle","race-condition"],"backgroundTag":"internal-invariant-violation","analyzedSha":"288d84d76e20a2f8f7173bda9691eb6ece301aa9","analyzedAt":"2026-09-11T11:29:36.208Z","contentChangedAt":"2026-09-11T11:29:36.208Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}