tonhowtf/omniget · warning

[omnidisc] dispatch handler failed

Error message

[omnidisc] dispatch handler failed

What it means

In the store's initialization, each `omnidisc://dispatch` event is wrapped in try/catch: if the user-supplied dispatch handling (handleDispatch) throws — e.g. a malformed payload from the backend or a bug in a message/state handler — the exception is contained and logged with the event type `payload.t`, so one bad event cannot crash the listener or the app.

Solutions

  1. Look at the logged payload.t and errorText(e) to identify which event handler threw
  2. Compare the dispatch payload shape against what handleDispatch expects (version skew between backend emitter and frontend parser)
  3. Add narrowing/validation inside the specific failing handler instead of relying on this outer catch
  4. Restart/reconnect the gateway to replay state after fixing the handler

Example fix

// before
handleDispatch(instance, payload.t, payload.d);
// after
try {
  handleDispatch(instance, payload.t, payload.d);
} catch (e) {
  console.warn("[omnidisc] dispatch handler failed", payload.t, errorText(e));
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!instanceByUrl(payload.url)) return; // drop events for unknown instances early
if (typeof payload.t !== "string" || payload.d == null) return;

Type guard

function isDispatchPayload(p: unknown): p is { url: string; t: string; d: unknown } {
  return typeof p === "object" && p !== null &&
    typeof (p as any).url === "string" && typeof (p as any).t === "string";
}

Try / catch

try {
  handleDispatch(instance, payload.t, payload.d);
} catch (e) {
  console.warn("[omnidisc] dispatch handler failed", payload.t, errorText(e));
}

Prevention

When it happens

Trigger: A dispatch event arrives whose handler (handleDispatch → message/guild/voice-state apply functions) throws: unexpected payload shape, missing instance fields, or a throw inside ensureUser/applyVoiceState-style state updates while processing MESSAGE_CREATE, GUILD_*, VOICE_STATE_UPDATE, etc.

Common situations: Backend/frontend version skew where the payload schema changed; corrupted or partially migrated persisted state the handler reads; race conditions where a dispatch arrives before instances state is hydrated.

Related errors


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

Appendix: source

Thrown at src/lib/stores/omnidisc-store.svelte.ts:1430

  if (mapped.status === "connected") settleReady(ev.url, null);
  else if (mapped.status === "signed_out" || mapped.status === "error") settleReady(ev.url, mapped.error ?? "ERR_UNREACHABLE");
}

let unlisteners: UnlistenFn[] = [];

export async function initOmnidisc(): Promise<void> {
  ensureLoaded();
  if (initialized) return;
  initialized = true;
  try {
    const offDispatch = await listen<GatewayDispatchEvent>("omnidisc://dispatch", (event) => {
      const payload = event.payload;
      const instance = instanceByUrl(payload.url);
      if (!instance) return;
      try {
        handleDispatch(instance, payload.t, payload.d);
      } catch (e) {
        console.warn("[omnidisc] dispatch handler failed", payload.t, errorText(e));
      }
    });
    const offStatus = await listen<GatewayStatusEvent>("omnidisc://status", (event) => handleStatus(event.payload));
    const offUpload = await listen<unknown>("omnidisc://upload", (event) => handleUploadProgress(event.payload));
    const offDecrypted = await listen<unknown>("omnidisc://decrypted", (event) =>
      handleDecryptedEvent(event.payload),
    );
    unlisteners = [offDispatch, offStatus, offUpload, offDecrypted];
  } catch (e) {
    initialized = false;
    console.warn("[omnidisc] could not subscribe to gateway events", errorText(e));
    return;
  }
  for (const instance of instances) {
    if (isDemo(instance.id)) continue;
    void connectGateway(instance);
  }
}

View on GitHub (pinned to 8600b91f42)