amir20/dozzle · error · Error

cloud dispatcher missing

Error message

cloud dispatcher missing

What it means

WelcomeModal.vue throws this when the dispatchers list loads successfully but contains no entry with type === 'cloud'. The rule-creation flow requires a cloud dispatcher to route alerts through and refuses to continue without one.

Solutions

  1. Link Dozzle Cloud first so the cloud dispatcher is provisioned, then retry the setup
  2. Check GET /api/notifications/dispatchers output to see which dispatcher types actually exist
  3. Verify the expected type string is exactly "cloud" against the backend dispatcher factory
  4. Guard the flow: show a setup step for linking Cloud instead of throwing mid-way

Example fix

// before
const cloud = dispatchers.find((d) => d.type === "cloud");
if (!cloud) throw new Error("cloud dispatcher missing");
// after
const cloud = dispatchers.find((d) => d.type === "cloud");
if (!cloud) {
  showToast({ type: "warning", message: t("notifications.cloud-not-linked") });
  return; // or redirect to Cloud linking step
}
Defensive patterns

Strategy: fallback

Validate before calling

const dispatchers: Array<{ id: number; type: string }> = await dispatchersRes.json();
const hasCloud = dispatchers.some((d) => d.type === "cloud");
if (!hasCloud) { /* show cloud-linking step instead of proceeding */ }

Type guard

function isCloudDispatcher(d: { type: string }): boolean {
  return d.type === "cloud";
}

Try / catch

try {
  setupRulesWithCloud(cloud);
} catch (e) {
  if (e instanceof Error && e.message === "cloud dispatcher missing") {
    showCloudLinkStep(); // graceful fallback instead of a dead-end toast
  }
}

Prevention

When it happens

Trigger: GET /api/notifications/dispatchers returns a list whose `type` values never equal "cloud" (only email/webhook/etc.), or an empty list.

Common situations: User never linked Dozzle Cloud (no cloud dispatcher provisioned), running a build where the dispatcher type string was renamed, or the cloud plugin/dispatcher failed to register server-side.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07). Data as JSON: /api/errors/69e650bab71674dd. Report an issue: GitHub.

Appendix: source

Thrown at assets/components/WelcomeModal.vue:553

  const chosen = activeRules.value;
  if (chosen.length === 0) {
    createdCount.value = 0;
    reportUsage(true);
    step.value = 3;
    return;
  }

  creating.value = true;
  abortController?.abort();
  abortController = new AbortController();
  const signal = abortController.signal;

  try {
    const dispatchersRes = await fetch(withBase("/api/notifications/dispatchers"), { signal });
    if (!dispatchersRes.ok) throw new Error("dispatchers fetch failed");
    const dispatchers: Array<{ id: number; type: string }> = await dispatchersRes.json();
    const cloud = dispatchers.find((d) => d.type === "cloud");
    if (!cloud) throw new Error("cloud dispatcher missing");

    // Fire rule POSTs in parallel. Partial failure is not cleaned up — if one
    // rejects, the earlier ones are already saved and the user lands on the
    // fallback toast path. Acceptable for a welcome modal; the user can edit
    // or delete rules from /notifications.
    await Promise.all(
      chosen.map((rule) =>
        fetch(withBase("/api/notifications/rules"), {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          signal,
          body: JSON.stringify({
            name: rule.ruleName,
            enabled: true,
            dispatcherId: cloud.id,
            containerExpression: "true",
            logExpression: rule.kind === "log" ? rule.expression : "",
            eventExpression: rule.kind === "event" ? rule.expression : "",

View on GitHub (pinned to d9463cbe21)