jlcodes99/cockpit-tools · warning

[account-sync] Failed to emit ${eventName}:

Error message

[account-sync] Failed to emit ${eventName}:

What it means

emitAccountSyncEvent wraps a Tauri event `emit` call in try/catch; if the cross-window event emission rejects, the failure is logged with this warning instead of propagating. This means other windows did NOT receive the account sync event, so account state can silently diverge between windows. The error is swallowed deliberately because sync events are best-effort.

Source

Thrown at src/utils/accountSyncEvents.ts:72

  return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, '_');
}

function resolveSourceWindowLabel(): string | undefined {
  try {
    return getCurrentWindow().label;
  } catch {
    return undefined;
  }
}

async function emitAccountSyncEvent(eventName: string, payload: AccountSyncEventPayload) {
  try {
    await emit<AccountSyncEventPayload>(eventName, {
      ...payload,
      sourceWindowLabel: payload.sourceWindowLabel ?? resolveSourceWindowLabel(),
    });
  } catch (error) {
    console.warn(`[account-sync] Failed to emit ${eventName}:`, error);
  }
}

export function normalizeProviderPagePlatformId(platformKey: string): PlatformId | null {
  const normalized = normalizePlatformKey(platformKey);
  return (
    PROVIDER_PAGE_PLATFORM_MAP[normalized] ??
    PROVIDER_PAGE_PLATFORM_MAP[normalized.replace(/_/g, '')] ??
    null
  );
}

export async function emitAccountsChanged(payload: AccountSyncEventPayload) {
  await emitAccountSyncEvent(ACCOUNTS_CHANGED_EVENT, payload);
}

export async function emitCurrentAccountChanged(payload: AccountSyncEventPayload) {
  await emitAccountSyncEvent(CURRENT_ACCOUNT_CHANGED_EVENT, payload);

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Read the logged `error` to see if it is a serialization error; make the payload JSON-safe (plain objects, strings, numbers only)
  2. Check window/app lifecycle: delay emits until the Tauri runtime is ready (e.g. after 'tauri://created') and guard emits after unmount
  3. Confirm sourceWindowLabel resolution (resolveSourceWindowLabel) isn't throwing upstream and the event name matches a registered listener
  4. Add a reconciliation mechanism (re-read accounts on window focus) so a missed event doesn't leave stale state

Example fix

// before
await emit(eventName, { ...payload, updatedAt: new Date() });
// after
await emit(eventName, { ...payload, updatedAt: new Date().toISOString() });
Defensive patterns

Strategy: try-catch

Validate before calling

function isEmitPayloadSafe(payload: unknown): boolean {
  try {
    structuredClone(payload);
    return true;
  } catch {
    return false;
  }
}

Type guard

function isPlainObject(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v) && Object.getPrototypeOf(v) === Object.prototype;
}

Try / catch

try {
  await emit(eventName, payload);
} catch (error) {
  console.warn(`[account-sync] Failed to emit ${eventName}:`, error);
  queueMicrotask(() => broadcastStateSnapshot()); // reconcile on next tick
}

Prevention

When it happens

Trigger: await emit<AccountSyncEventPayload>(eventName, ...) rejects — typically when the Tauri IPC/event bridge is unavailable (webview not ready, app shutting down, window closed mid-emit) or the payload fails serialization (non-JSON-safe values like undefined fields that break structured clone, functions, or circular refs).

Common situations: Firing account-sync events during app startup/teardown races; emitting from a secondary window that just closed; payload accidentally containing class instances or circular references after refactors.

Related errors


AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05). Data as JSON: /api/errors/99f0430b908bec0a. Report an issue: GitHub.