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
- Look at the logged payload.t and errorText(e) to identify which event handler threw
- Compare the dispatch payload shape against what handleDispatch expects (version skew between backend emitter and frontend parser)
- Add narrowing/validation inside the specific failing handler instead of relying on this outer catch
- 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
- Validate dispatch payloads inside each handler rather than trusting backend shape
- Keep backend event emitters and frontend handlers in version lockstep
- Never let one handler's throw escape the listener loop
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
- [omnidisc] could not sign out of
- [omnidisc] could not load messages
- [omnidisc] could not load older messages
- [omnidisc] could not subscribe to gateway events
- [omnidisc] invite could not be redeemed
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)