Skip to content

Surface Query Store plan-load failures instead of silent 'No Plan Loaded'#367

Merged
erikdarlingdata merged 1 commit into
devfrom
fix/qs-plan-load-surface-errors
Jun 15, 2026
Merged

Surface Query Store plan-load failures instead of silent 'No Plan Loaded'#367
erikdarlingdata merged 1 commit into
devfrom
fix/qs-plan-load-surface-errors

Conversation

@erikdarlingdata

Copy link
Copy Markdown
Owner

Problem

Loading a plan from the Query Store grid could blank to "No Plan Loaded" while the QS grid itself vanished, with no explanation.

Root cause

  • PlanViewerControl.LoadPlan treated a failed parse identically to an empty plan: ShowPlanParser.Parse never throws — it records failures in ParsedPlan.ParseError and returns a zero-statement plan — but the desktop app never read ParseError, so any parse failure rendered as a bare "No Plan Loaded".
  • AddPlanTab unconditionally added and selected the new plan tab even when the load failed, navigating away from the grid to that blank tab.

Commit e8e5a21 (parser hardening) was the regression vector: it wrapped the parser tree-walk in a catch-all, converting what used to be a visible crash on a bad plan into a silent zero-statement ParseError — i.e. exactly this symptom.

Fix

  • LoadPlan returns bool and exposes LastLoadError, distinguishing blank/NULL plan XML, a parse error (surfaced verbatim in the empty-state panel), and parsed-but-no-statements.
  • AddPlanTab no longer switches away on failure — it keeps the Query Store grid active and leaves a persistent status line explaining why.
  • Clear() resets the empty state so a reused viewer can't show a stale error (caught by the Avalonia gotcha review).

The four direct LoadPlan callers (File→Open, paste, estimated/actual execution) ignore the new return value and keep their prior behavior; they additionally benefit from real error text in the empty state.

Note

This makes failures visible and non-destructive; it does not alter the parser. If a specific plan still fails, the on-screen "Parse error: …" now names the cause so the underlying parser issue can be fixed separately.

Testing

  • dotnet build PlanViewer.App: 0 errors.
  • App launches clean; empty state renders with no Avalonia binding errors.
  • Avalonia gotcha review: clean (no null-element risk, no event-handler leak, no orphaned MCP session — failed loads never register one).

🤖 Generated with Claude Code

…ded"

Loading a plan from the Query Store grid could blank to "No Plan Loaded" while
the grid vanished, with no indication why. Two compounding causes:

- PlanViewerControl.LoadPlan treated a failed parse identically to an empty
  plan: it never inspected ParsedPlan.ParseError (which ShowPlanParser sets
  instead of throwing) and just showed the empty state on zero statements.
- AddPlanTab unconditionally added and selected the new plan tab even when the
  load failed, navigating away from the grid to a blank tab.

(Commit e8e5a21's parser hardening was the regression vector: it converted a
tree-walk exception on a bad plan from a visible crash into a silent
zero-statement ParseError, producing exactly this symptom.)

LoadPlan now returns bool and exposes LastLoadError, distinguishing blank/NULL
plan XML, a parse error (surfaced verbatim), and parsed-but-no-statements.
AddPlanTab no longer switches away on failure -- it keeps the grid active and
leaves a persistent status explaining why. Clear() resets the empty state so a
reused viewer cannot show a stale error.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@erikdarlingdata erikdarlingdata merged commit 3e33ed7 into dev Jun 15, 2026
2 checks passed
@erikdarlingdata erikdarlingdata deleted the fix/qs-plan-load-surface-errors branch June 15, 2026 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant