tonhowtf/omniget · warning
[omnidisc] voice leave failed
Error message
[omnidisc] voice leave failed
What it means
leaveVoice invokes the backend command `omnidisc_voice_leave` to disconnect from the voice session. On rejection (no active session backend-side, command panic, or missing command), the warning is logged, but the finally block unconditionally clears session, connState, speaking, and quality — so the UI shows disconnected even if the backend did not actually leave.
Solutions
- Make the backend leave idempotent: Ok when there is no session to leave.
- Guard the frontend: skip the invoke when session is null (local state reset only).
- Reconcile after failure by re-fetching `omnidisc_voice_status` to confirm actual connection state.
- Debounce the leave button to prevent duplicate concurrent invokes.
Example fix
// before
await invoke("omnidisc_voice_leave");
// after
if (session !== null) {
try { await invoke("omnidisc_voice_leave"); }
finally { /* reset local state */ }
} Defensive patterns
Strategy: try-catch
Validate before calling
if (session === null) { resetLocalVoiceState(); return; } Try / catch
busy = true;
try {
await invoke("omnidisc_voice_leave");
} catch (e) {
console.warn("[omnidisc] voice leave failed", errorText(e));
await reconcileVoiceStatus(); // re-fetch omnidisc_voice_status
} finally {
busy = false;
session = null;
connState = "idle";
} Prevention
- Skip the invoke when there is no local session; just reset state.
- Make backend leave idempotent for already-closed sessions.
- Debounce the leave control to prevent duplicate concurrent invokes.
- After a failed leave, re-fetch voice status to confirm the true connection state.
When it happens
Trigger: Calling leaveVoice() when the backend has no active voice session (already left, connection dropped), the Rust `omnidisc_voice_leave` command panics (e.g. connection object already closed), or frontend/backend command-name skew.
Common situations: Closing the app/window while voice is connecting; network drop causing the backend to clean up first; double-clicking the leave button; stale session after a reconnect replaced the backend connection.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- [omnidisc] mute failed
- [omnidisc] deafen failed
- e.to_string()
- [omnidisc] media capabilities unavailable
- [omnidisc] stop stream failed
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/56a8bd7a140764fa.
Report an issue: GitHub.
Appendix: source
Thrown at src/lib/stores/omnidisc-voice-store.svelte.ts:579
outputError = result.output_error ?? null;
syncStatsPolling();
return true;
} catch (e) {
lastError = errorText(e);
connState = "failed";
syncStatsPolling();
return false;
} finally {
busy = false;
}
}
export async function leaveVoice(): Promise<void> {
busy = true;
try {
await invoke("omnidisc_voice_leave");
} catch (e) {
console.warn("[omnidisc] voice leave failed", errorText(e));
} finally {
busy = false;
session = null;
connState = "idle";
speaking = {};
quality = "unknown";
lastError = null;
micError = null;
outputError = null;
syncStatsPolling();
}
}
export async function retryVoice(): Promise<boolean> {
const target = session?.channelId;
if (!target) return false;
return joinVoice(target);
}View on GitHub (pinned to 8600b91f42)