Skip to content

Interactive window kernel picker has no effect on queries re-run from a .kql file #141

@pjanowski

Description

@pjanowski

Interactive window kernel picker has no effect on queries re-run from a .kql file

Affected versions: confirmed on main (0.6.0) and on the published marketplace build 0.5.4.

Summary

When a .kql file is run via the Kusto Interactive Window, the connection used to execute the query is fixed at the time the interactive window is first opened. Subsequently changing the kernel via the interactive window's kernel picker updates the UI but does not affect subsequent runs initiated from the source .kql file — they keep executing against the original connection.

Repro

  1. Open any .kql file. Bind it to cluster A / db A via the $(database) icon in the editor title bar.
  2. Select "Run Query" code lense. The Kusto Interactive Window opens, executing against cluster A. (Pick a cluster where the query is expected to fail, e.g. a database that lacks a function referenced in the query — this makes the bug visually obvious.)
  3. In the interactive window, click the kernel dropdown → "Select Another Kernel" → "Kusto" → pick cluster B / db B (the connection the query should actually use).
  4. Back in the source .kql file, Run Query.

Expected: the query runs against cluster B (the kernel the user just selected).

Actual: the query still runs against cluster A. If A was a failing connection, the same failure repeats; if A was a wrong-data connection, results come from the wrong cluster with no visible indicator. The interactive window's kernel selector continues to show cluster B even though execution silently routes to A.

Root cause

src/extension/interactive/interactive.ts keeps documentInteractiveDocuments, a WeakMap<TextDocument, Promise<readonly [NotebookDocument, KernelPerConnection]>>. The KernelPerConnection value is the controller captured at the time getNotebookDocument() first resolved the document's connection. The cache is only invalidated when the interactive notebook closes (info[0].isClosed):

if (!info || info[0].isClosed) {
    documentInteractiveDocuments.set(document, getNotebookDocument(document));
}
...
const [notebook, controller] = info;
...
await controller.executeInteractive([cell], document);   // ← stale controller

KernelPerConnection.executeCell then calls Client.create(... this.connection), where this.connection is the controller's fixed connection — completely independent of whatever the user picked in the kernel UI.

The kernel picker correctly fires onDidChangeSelectedNotebooks on the newly-selected controller (KernelPerConnection constructor), but the handler only writes to globalState. Nothing updates documentInteractiveDocuments, so subsequent kusto.executeSelectedQuery invocations from the source .kql keep routing through the stale controller.

Workaround (no extension change)

  1. With the .kql file focused, click the $(database) icon in the editor title bar to rebind the per-file connection. This updates the globalState entry that pickConnection reads on cache miss.
  2. Close any existing "Kusto Interactive Window" tab — this trips the info[0].isClosed branch.
  3. Re-run from the .kql file. The cache re-resolves to the now-correct controller.

Sometimes these steps fail (couldn't figure out when): bind file to correct database but when Run Query selected the Kusto Interactive Window tab still opens with old DB.

The in-window kernel picker is effectively decorative for .kql-driven execution today.

Suggested fix

Track the currently-selected controller per notebook in provider.ts (the existing onDidChangeSelectedNotebooks already provides the signal) and look it up at execute time from executeSelectedQuery. PR with implementation: TODO link after PR is opened.

Environment

  • VS Code: any recent
  • Extension: donjayamanne.kusto 0.5.4 (marketplace) — bug also present on microsoft/vscode-ext-kusto@main (0.6.0)
  • OS: WSL2 Ubuntu 24.04 + Windows 11 host (also reproduces on plain Windows (tried) and on macOS (by code inspection))

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions