{"record":{"id":"2df6780c45a65c62","repo":"amir20/dozzle","slug":"rule-post-failed","errorCode":null,"errorMessage":"rule POST failed","messagePattern":"rule POST failed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"assets/components/WelcomeModal.vue","lineNumber":577,"sourceCode":"    await Promise.all(\n      chosen.map((rule) =>\n        fetch(withBase(\"/api/notifications/rules\"), {\n          method: \"POST\",\n          headers: { \"Content-Type\": \"application/json\" },\n          signal,\n          body: JSON.stringify({\n            name: rule.ruleName,\n            enabled: true,\n            dispatcherId: cloud.id,\n            containerExpression: \"true\",\n            logExpression: rule.kind === \"log\" ? rule.expression : \"\",\n            eventExpression: rule.kind === \"event\" ? rule.expression : \"\",\n            metricExpression: rule.kind === \"metric\" ? rule.expression : \"\",\n            cooldown: rule.cooldown,\n            sampleWindow: rule.sampleWindow,\n          }),\n        }).then((res) => {\n          if (!res.ok) throw new Error(\"rule POST failed\");\n        }),\n      ),\n    );\n\n    createdCount.value = chosen.length;\n    reportUsage(false);\n    step.value = 3;\n  } catch (err) {\n    if ((err as Error)?.name === \"AbortError\") return;\n    close();\n    showToast({ type: \"warning\", message: t(\"notifications.default-alert-failed\") }, { expire: 6000 });\n    router.push({ path: \"/notifications\", query: { action: \"create-alert\" } });\n  } finally {\n    creating.value = false;\n  }\n}\n\nfunction skipAlerts() {","sourceCodeStart":559,"sourceCodeEnd":595,"githubUrl":"https://github.com/amir20/dozzle/blob/d9463cbe21874e44ab79db6fa63e746ca7d22928/assets/components/WelcomeModal.vue#L559-L595","documentation":"WelcomeModal.vue fires parallel POSTs to create notification rules and each POST's .then throws 'rule POST failed' when res.ok is false. Because the POSTs run via Promise.all, a single failing rule aborts the whole setup after earlier rules may already be saved (documented partial-failure behavior).","triggerScenarios":"Any rule-creation POST returns 4xx/5xx: invalid expression syntax for the rule kind, missing cooldown/sampleWindow fields, server validation rejecting the payload, or auth failure.","commonSituations":"A metric or event expression the backend validator rejects; notifications persistence directory not writable so the second+ rule fails; session expired between the dispatchers fetch and the rule POSTs.","solutions":["Check each failing POST's status and response body in devtools to find which rule and why","Validate rule expressions (kind, expression syntax, cooldown/sampleWindow ranges) before submitting","Replace Promise.all with Promise.allSettled if partial success should be reported per-rule","Confirm auth is still valid and the data directory is writable for notifications.yml"],"exampleFix":"// before\n}).then((res) => {\n  if (!res.ok) throw new Error(\"rule POST failed\");\n}),\n// after\n}).then((res) => {\n  if (!res.ok) throw new Error(`rule POST failed for \"${rule.name}\" (HTTP ${res.status})`);\n}),","handlingStrategy":"validation","validationCode":"for (const rule of chosen) {\n  if (!rule.expression?.trim()) throw new Error(`Rule \"${rule.name}\" has an empty expression`);\n  if (!Number.isFinite(rule.cooldown) || rule.cooldown < 0) throw new Error(`Rule \"${rule.name}\" has invalid cooldown`);\n}","typeGuard":null,"tryCatchPattern":"const results = await Promise.allSettled(chosen.map((rule) => postRule(rule)));\nconst failed = results.filter((r) => r.status === \"rejected\");\nif (failed.length) showToast({ type: \"warning\", message: `${chosen.length - failed.length} of ${chosen.length} rules created` });","preventionTips":["Validate rule expressions and numeric fields before submitting","Use Promise.allSettled when partial success is acceptable","Check notifications.yml writability once before batch-creating rules","Include rule identity in thrown messages to identify the failing POST"],"tags":["http","vue","notifications","parallel-requests"],"backgroundTag":"http-error-response","analyzedSha":"d9463cbe21874e44ab79db6fa63e746ca7d22928","analyzedAt":"2026-09-07T10:08:55.855Z","contentChangedAt":"2026-09-07T10:08:55.855Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}