koala73/worldmonitor · warning · IncompatibleDeliveryError

INCOMPATIBLE_DELIVERY

INCOMPATIBLE_DELIVERY

Error message

Real-time delivery requires High or Critical sensitivity.

What it means

Default message for IncompatibleDeliveryError, thrown by setNotificationConfig() in src/services/notification-channels.ts when POST /api/notification-channels (action=set-notification-config) answers 400 with body.error === 'INCOMPATIBLE_DELIVERY'. The server's cross-field validator rejects digestMode 'realtime' paired with sensitivity 'all' — real-time delivery is only allowed with High or Critical sensitivity (plan forbid-realtime-all-events.md §1f). The dedicated error class lets the settings UI render inline helper text instead of a generic failure; the exact server message overrides this default when present.

Source

Thrown at src/services/notification-channels.ts:463

  sensitivity?: Sensitivity;
  channels?: ChannelType[];
  aiDigestEnabled?: boolean;
  digestMode?: DigestMode;
  digestHour?: number;
  digestTimezone?: string;
  countries?: string[];
  tickers?: string[];
}, expectedUserId?: string, signal?: AbortSignal): Promise<void> {
  const res = await authFetch('/api/notification-channels', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ action: 'set-notification-config', ...args }),
  }, expectedUserId, signal);
  if (res.ok) return;
  let body: { error?: string; message?: string } = {};
  try { body = await res.json(); } catch { /* keep default */ }
  if (res.status === 400 && body.error === 'INCOMPATIBLE_DELIVERY') {
    throw new IncompatibleDeliveryError(
      body.message ?? 'Real-time delivery requires High or Critical sensitivity.',
    );
  }
  throw new Error(`set notification config: ${res.status}`);
}

View on GitHub (pinned to eeab0a219f)

Solutions

  1. Set sensitivity to 'high' or 'critical' in the same call that sets digestMode: 'realtime' — the endpoint applies both atomically.
  2. Pre-validate the pair client-side before POSTing (mirror the rule) so the user gets feedback before submit.
  3. Catch IncompatibleDeliveryError specifically (instanceof) and show the server's body.message inline rather than a generic error.
  4. If migrating legacy configs, upgrade sensitivity in the same payload when switching to realtime.

Example fix

// before
await setNotificationConfig({ variant: 'global', digestMode: 'realtime', sensitivity: 'all' });

// after
const sensitivity = args.digestMode === 'realtime' && args.sensitivity === 'all'
  ? 'high'
  : args.sensitivity;
await setNotificationConfig({ ...args, sensitivity });
Defensive patterns

Strategy: validation

Validate before calling

const REALTIME_SENSITIVITY = new Set(['high', 'critical']);

if (config.digestMode === 'realtime' && !REALTIME_SENSITIVITY.has(config.sensitivity)) {
  showInlineError('Real-time delivery requires High or Critical sensitivity.');
  return;
}
await setNotificationConfig(config);

Type guard

import { IncompatibleDeliveryError } from '@/services/notification-channels';

function isIncompatibleDelivery(err: unknown): err is IncompatibleDeliveryError {
  return err instanceof IncompatibleDeliveryError;
}

Try / catch

try {
  await setNotificationConfig(args);
} catch (err) {
  if (isIncompatibleDelivery(err)) {
    showInlineHelper(err.message); // render guidance, keep the form open
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling setNotificationConfig({ digestMode: 'realtime', sensitivity: 'all', ... }) (or leaving sensitivity at 'all' while switching digestMode to 'realtime'); a UI flow that saves digest mode and sensitivity in separate steps can also trip the validator transiently; any API consumer that assumes the (realtime, all) pair is accepted.

Common situations: Users switching from daily digest to real-time without raising sensitivity first; stale clients after the validation rule shipped, still sending the previously-legal combination; form state bugs that reset sensitivity to 'all' silently.

Related errors


AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21). Data as JSON: /api/errors/b03e155fcc875665. Report an issue: GitHub.