Remove redundant binaryAvailable guard from TailscaleWidget.qml #11
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
binaryAvailable (line 14) is a boolean property that starts true and only flips to false when statusCheck exits with code 127 (command not found). It's used as a preemptive guard in toggleTailscale() and setExitNode() before running a Process.
Problems:
Stale state — The property is only evaluated during statusCheck runs, which fire every 5 seconds via a timer. If the binary is uninstalled, moved, or becomes broken between checks, the guard still thinks it's available and allows the user to click through to toggleTailscale() or setExitNode(). The guard provides a false sense of safety for up to 5 seconds after the condition actually changes. Even at the moment of the check, there's a race: the binary could disappear between the statusCheck confirming it exists and the user clicking a button that invokes toggleProcess or exitNodeProcess.
No recovery — Once binaryAvailable flips to false, there's no mechanism to reset it back to true. The periodic timer continues firing, but statusCheck will keep failing (since the binary is gone), so the property is stuck. Even if the user reinstalls Tailscale while the widget is running, the widget remains in the "not available" state until the plugin is reloaded or Quickshell is restarted. This means the guard is a one-way trip that degrades the user experience permanently for the session.
Redundant — Each Process already has an onExited handler that shows an error toast on non-zero exit codes. The actual failure path is already covered whether the binary is missing, permission-denied, or crashes.
Unnecessary UI state — The StyledText at line 160 only shows when binaryAvailable is false, adding dead UI branches and layout calculations for a state that's both unreliable and unrecoverable.
FYI from cross-model audit (claude-sonnet-4-6):
When
binaryAvailable = false, the centered "Tailscale not available" StyledText renders, butstatusRowandpeerListlackvisible: root.binaryAvailableguards. They continue to draw underneath/over the notice, producing overlapping/confusing UI.If the decision is to keep or evolve the binaryAvailable state instead of removing it entirely, this visibility bug must be fixed so the error state actually hides the normal content.
FYI from cross-model audit (claude-sonnet-4-6):
binaryAvailableis initialized totrue. On startup the widget therefore shows the normal status row and peer list for up to one full 5-second timer interval before the firststatusCheckcan possibly set it tofalse. If the binary is absent, users briefly see a fully functional UI that then flips to the error state.This is another concrete failure mode of the current
binaryAvailableguard logic (in addition to the stale-state and one-way-trip problems already noted in this issue).Related: #13 (duplicate error toasts on statusCheck), #14 (stale isConnected), #30 (multiple concurrent statusCheck triggers). All stem from the same 5 s polling + state model.
Resolved by removing binaryAvailable property, its setter, guards in toggle/setExitNode, and the dead 'not available' UI text. All error paths now rely on Process onExited handlers which already exist. Changes merged to vibes branch. No human review needed for verification as it's a pure removal of dead/redundant code with no behavior change for normal operation. Written by AI agent working for @jtmorris. Model: Grok 4.3.
Resolved via merge
ac1669f(feature_remove_binaryavailable_guard). The plugin is confirmed working by @jtmorris. Human code review required before merging to testing.