tonhowtf/omniget · warning
[omnidisc] stream volume failed
Error message
[omnidisc] stream volume failed
What it means
setStreamVolume invokes `omnidisc_stream_set_volume` with a gain clamped to [0, 2]. If the backend rejects (unknown user, no active audio sink for that user, command panic), the warning is logged and the volume simply is not applied. No state changes occur in the catch path.
Solutions
- Guard the call: only invoke when the backend reports the user as watched (check stream stats or watchingIds and a live-sink flag).
- Validate gain is a finite number before clamping: Number.isFinite(gain).
- Re-apply volume after watch completes (retry once the stream is established).
- Inspect the backend error to confirm the audio sink exists for that userId.
Example fix
// before
await invoke("omnidisc_stream_set_volume", { userId, gain: Math.min(2, Math.max(0, gain)) });
// after
if (!Number.isFinite(gain)) return;
await invoke("omnidisc_stream_set_volume", { userId, gain: Math.min(2, Math.max(0, gain)) }); Defensive patterns
Strategy: validation
Validate before calling
if (!Number.isFinite(gain) || gain < 0 || gain > 2) return; if (!watchingIds.includes(userId)) return;
Type guard
function isValidGain(g: unknown): g is number {
return typeof g === 'number' && Number.isFinite(g) && g >= 0 && g <= 2;
} Try / catch
try {
await invoke("omnidisc_stream_set_volume", { userId, gain: clamp(gain, 0, 2) });
} catch (e) {
console.warn("[omnidisc] stream volume failed", errorText(e));
scheduleVolumeRetry(userId, gain); // re-apply once stream is live
} Prevention
- Clamp and validate gain (reject NaN) before invoking.
- Only allow volume changes for users with an active audio sink.
- Re-apply the desired volume after watch completes, since early sets can fail.
- Ignore slider events for streams that just ended.
When it happens
Trigger: Calling setStreamVolume(userId, gain) for a userId with no active watched stream/audio element in the backend, a NaN gain (NaN bypasses min/max clamping), or a backend that has torn down the audio sink for that peer.
Common situations: Moving a volume slider while the remote stream just ended; volume applied before the watch handshake completes; NaN produced by an uncontrolled input parsed to a number.
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] volume failed
- [omnidisc] mute failed
- [omnidisc] deafen failed
- [omnidisc] noise suppression failed
- [omnidisc] ducking failed
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/8ab182fd70db5582.
Report an issue: GitHub.
Appendix: source
Thrown at src/lib/stores/omnidisc-stream-store.svelte.ts:299
busy = false;
}
}
export async function unwatchStream(userId: string): Promise<void> {
try {
await invoke("omnidisc_stream_unwatch", { userId });
} catch (e) {
console.warn("[omnidisc] unwatch failed", errorText(e));
} finally {
watchingIds = watchingIds.filter((id) => id !== userId);
}
}
export async function setStreamVolume(userId: string, gain: number): Promise<void> {
try {
await invoke("omnidisc_stream_set_volume", { userId, gain: Math.min(2, Math.max(0, gain)) });
} catch (e) {
console.warn("[omnidisc] stream volume failed", errorText(e));
}
}
export async function refreshStreamStats(): Promise<StreamStats | null> {
try {
stats = await invoke<StreamStats>("omnidisc_stream_stats");
if (stats.publishing) publishing = stats.publishing;
return stats;
} catch {
return null;
}
}
interface StreamEventPayload {
type: string;
audio?: AudioMode;
user_id?: string;
active?: boolean;View on GitHub (pinned to 8600b91f42)