tonhowtf/omniget · warning · StreamError

e.code().to_string()

Error message

e.code().to_string()

What it means

stream.rs defines a helper err(e: StreamError) -> String that maps a StreamError to its machine-readable error code via e.code().to_string() — the message shown here is the dynamic code value produced by that mapping. These strings are the error contract returned by the omnidisc stream Tauri commands (e.g. "BACKEND_UNAVAILABLE"-style codes).

Solutions

  1. In the frontend, match on the returned code string instead of displaying it raw; map codes to user-facing messages.
  2. Check backend() configuration (omnidisc_voice state) before invoking stream commands to avoid backend-unavailable codes.
  3. Include the error detail alongside the code (e.g. format!("{}: {}", e.code(), e)) for easier debugging.
  4. Define the codes as an enum shared between Rust and TS to avoid string mismatches.

Example fix

// before
fn err(e: StreamError) -> String {
    e.code().to_string()
}

// after
fn err(e: StreamError) -> String {
    format!("{}: {}", e.code(), e) // keep code stable prefix, add human-readable detail
}
Defensive patterns

Strategy: type-guard

Validate before calling

const STREAM_CODES = new Set(['BACKEND_UNAVAILABLE', 'PREVIEW_FAILED', 'VIEWER_LIMIT']);
function isStreamCode(v: unknown): v is string {
  return typeof v === 'string' && STREAM_CODES.has(v);
}

Type guard

function isStreamCode(v: unknown): v is StreamErrorCode {
  return typeof v === 'string' && STREAM_CODES.includes(v as StreamErrorCode);
}

Try / catch

try {
  await invoke('omnidisc_stream_preview', args);
} catch (e) {
  if (isStreamCode(e)) showError(STREAM_CODE_MESSAGES[e]);
  else showError(String(e));
}

Prevention

When it happens

Trigger: Any omnidisc stream command that returns Result<_, String> converts its StreamError through err(), surfacing e.code().to_string() to the frontend; the frontend then receives the code string as the rejection reason.

Common situations: Frontend calls a stream command while the LiveKit backend is not configured/connected; preview or viewer operations run against an uninitialized state; handling the rejection expecting a human message but receiving a bare code.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/addbb50197697cff. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/src/commands/omnidisc/stream.rs:31

use tokio::sync::Mutex;

pub struct StreamManager {
    active: Mutex<Option<ActiveStream>>,
    viewers: Mutex<HashMap<String, Viewer>>,
    preview_gen: AtomicU64,
}

impl Default for StreamManager {
    fn default() -> Self {
        Self {
            active: Mutex::new(None),
            viewers: Mutex::new(HashMap::new()),
            preview_gen: AtomicU64::new(0),
        }
    }
}

fn err(e: StreamError) -> String {
    e.code().to_string()
}

fn backend(state: &crate::AppState) -> Result<Arc<LiveKitBackend>, String> {
    state
        .omnidisc_voice
        .livekit_backend()
        .ok_or_else(|| "ERR_VOICE_UNAVAILABLE".to_string())
}

fn emit_voice(
    app: &tauri::AppHandle,
    url: Option<String>,
    event: &str,
    mut payload: serde_json::Value,
) {
    if let serde_json::Value::Object(map) = &mut payload {
        map.insert("type".into(), json!(event));

View on GitHub (pinned to 8600b91f42)