{"record":{"id":"143e9379c7e97a85","repo":"odysseus-dev/odysseus","slug":"webhook-reminder-was-not-sent-activechannel","errorCode":null,"errorMessage":"Webhook reminder was not sent${activeChannel}","messagePattern":"Webhook reminder was not sent(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"static/js/settings.js","lineNumber":2714,"sourceCode":"            llm_synthesis: !!(llmToggle && llmToggle.checked),\n            llm_persona: (personaSel && personaSel.value) || '',\n            ...(channelSel.value === 'webhook' ? {\n              webhook_integration_id: webhookIntgSel?.value || '',\n              webhook_payload_template: webhookTemplateIn?.value.trim() || '',\n            } : {}),\n          }),\n        });\n        const data = await res.json();\n        if (!res.ok) throw new Error(data.detail || 'Server error');\n        if (channelSel.value === 'email' && !data.email_sent) {\n          throw new Error(data.email_error || 'Email reminder was not sent');\n        }\n        if (channelSel.value === 'ntfy' && !data.ntfy_sent) {\n          throw new Error(data.ntfy_error || 'ntfy reminder was not sent');\n        }\n        if (channelSel.value === 'webhook' && !data.webhook_sent) {\n          const activeChannel = data.channel ? ` (server used channel: \"${data.channel}\")` : '';\n          throw new Error((data.webhook_error || 'Webhook reminder was not sent') + activeChannel);\n        }\n        let status = 'Delivered via ' + channelSel.value;\n        if (data.synthesis) status += ' (AI: \"' + data.synthesis.slice(0, 60) + '...\")';\n        if (data.email_sent) status += ' — email sent';\n        if (data.ntfy_sent) status += ' — ntfy sent';\n        if (data.webhook_sent) status += ' — webhook sent';\n        if (testMsg) { testMsg.textContent = status; testMsg.style.color = 'var(--green, #50fa7b)'; }\n        // Also fire a browser notification so user can see it\n        if ('Notification' in window && Notification.permission === 'granted') {\n          try {\n            new Notification('Test Reminder', {\n              body: data.synthesis || 'This is a test reminder.',\n              tag: 'reminder-test',\n              icon: '/static/favicon.ico',\n            });\n          } catch {}\n        }\n      } catch (e) {","sourceCodeStart":2696,"sourceCodeEnd":2732,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/static/js/settings.js#L2696-L2732","documentation":"Delivery-level failure for webhook test reminders; the literal '${activeChannel}' in the source is a template interpolation — the real message appends (server used channel: \"X\") when the server reports which channel it actually used, exposing channel-mismatch situations. Thrown when channel is 'webhook' and data.webhook_sent is falsy.","triggerScenarios":"POST test returns 200 with {webhook_sent: false} — webhook integration id missing/deleted, payload template invalid, target URL unreachable, non-2xx from the target, or the server overriding the requested channel (visible via the appended channel note).","commonSituations":"Webhook integration deleted after selection; template references fields the payload lacks; target endpoint returns 401/404; server fell back to a different channel because the webhook config was incomplete.","solutions":["Inspect data.webhook_error and data.channel in the response body","Verify the chosen integration id still exists and its URL responds","Test the target endpoint directly with the rendered payload","If the appended note shows a different channel, fix why the server overrode 'webhook' (usually missing integration_id)"],"exampleFix":"// before\n          throw new Error((data.webhook_error || 'Webhook reminder was not sent') + activeChannel);\n\n// after\n          throw new Error((data.webhook_error || 'Webhook reminder was not sent (verify integration URL/template)') + activeChannel);","handlingStrategy":"try-catch","validationCode":"if (channelSel.value === 'webhook' && channelSel.value === 'webhook' && !webhookIntgSel?.value) {\n  if (testMsg) { testMsg.textContent = 'Select a webhook integration first'; testMsg.style.color = 'var(--red)'; }\n  return;\n}","typeGuard":null,"tryCatchPattern":"if (channelSel.value === 'webhook' && !data.webhook_sent) { const activeChannel = data.channel ? ` (server used channel: \"${data.channel}\")` : ''; throw new Error((data.webhook_error || 'Webhook reminder was not sent') + activeChannel); }","preventionTips":["Require a webhook integration selection before enabling test","Validate the payload template against the integration's schema","Log data.webhook_error and data.channel for mismatch diagnosis","Keep the activeChannel suffix — it exposes server-side channel overrides"],"tags":["reminders","webhook","delivery","settings"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}