affaan-m/ECC · error · anyhow::Error

returned

Error message

{} returned {}

What it means

Webhook notification delivery POSTs a JSON payload to the configured target URL; if the HTTP response status is not a success (2xx), the code raises this error including the URL and the response status code. It indicates the endpoint was reachable but rejected or failed the request.

Solutions

  1. Check the exact status code in the message: 4xx means fix the URL/token/payload, 5xx means retry later.
  2. Verify the webhook URL is current and valid by testing with `curl -X POST`.
  3. Confirm the payload matches what the receiver expects (field names, types).
  4. Add retry with backoff for transient 5xx/429 responses; update the target configuration if the endpoint was rotated.

Example fix

// before
{"targets":[{"url":"https://hooks.example.com/old-token"}]}
// after
{"targets":[{"url":"https://hooks.example.com/services/T000/B000/XXXX"}]}
Defensive patterns

Strategy: retry

Validate before calling

// validate the target before storing it
let resp = reqwest::blocking::Client::new().post(&url).json(&test_payload).send()?;
if !resp.status().is_success() {
    bail!("webhook target invalid: {} -> {}", url, resp.status());
}

Try / catch

match send_webhook(target, payload) {
    Err(e) if e.to_string().contains("returned 5") || e.to_string().contains("returned 429") => {
        // retry with backoff
        schedule_retry(target, payload, attempts + 1);
    }
    Err(e) => log::error!("webhook permanently failed: {e}"),
    Ok(()) => {}
}

Prevention

When it happens

Trigger: Webhook target returns 4xx (bad URL path, invalid auth token, malformed payload per receiver's schema) or 5xx (receiver internal error / 429 too many requests).

Common situations: Slack/Discord webhook URLs rotated or revoked (401/404); payload schema changed on the receiver side (400); rate limiting by the webhook provider (429); receiver service down (502/503).

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/3e95f40827faeaac. Report an issue: GitHub.

Appendix: source

Thrown at ecc2/src/notifications.rs:419

    Ok(())
}

#[cfg(not(test))]
fn send_webhook_request(target: &WebhookTarget, payload: serde_json::Value) -> Result<()> {
    let agent = ureq::Agent::config_builder()
        .timeout_connect(Some(std::time::Duration::from_secs(5)))
        .timeout_recv_response(Some(std::time::Duration::from_secs(5)))
        .build()
        .new_agent();
    let response = agent
        .post(&target.url)
        .send_json(payload)
        .with_context(|| format!("POST {}", target.url))?;

    if response.status().is_success() {
        Ok(())
    } else {
        anyhow::bail!("{} returned {}", target.url, response.status());
    }
}

#[cfg(test)]
fn send_webhook_request(_target: &WebhookTarget, _payload: serde_json::Value) -> Result<()> {
    Ok(())
}

fn sanitize_osascript(value: &str) -> String {
    value
        .replace('\\', "")
        .replace('"', "\u{201C}")
        .replace('\n', " ")
}

#[cfg(test)]
mod tests {
    use super::{

View on GitHub (pinned to 8321021c54)