amir20/dozzle · error
failed to send to cloud
Error message
failed to send to cloud: %w
What it means
This wraps the error returned by the HTTP client's Do() call when the POST to the Dozzle Cloud /api/events endpoint fails at the transport level. It means no HTTP response was received: connection refused, DNS failure, TLS error, timeout (client timeout is 10s), or context cancellation.
Solutions
- Inspect the wrapped %w cause with errors.Unwrap or %v to identify connection vs timeout vs DNS
- Verify outbound network/DNS from the Dozzle container (docker exec ... wget https://doligence.dozzle.dev)
- Check the DOLIGENCE_URL env var points to a reachable host if overridden
- Retry with backoff; transport errors are transient unless the endpoint is permanently blocked by firewall
Example fix
if err := d.Send(ctx, n); err != nil {
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
// retry with backoff
}
} Defensive patterns
Strategy: retry
Try / catch
var nErr net.Error
if errors.As(err, &nErr) && nErr.Timeout() {
// exponential backoff retry
} else {
// check connectivity/DNS before retrying
} Prevention
- Verify outbound internet/DNS from the container before enabling cloud notifications
- Check firewall/proxy rules for the cloud endpoint
- Set a sane DOLIGENCE_URL only when you control the target
When it happens
Trigger: Calling CloudDispatcher.Send when the network is down, DNS cannot resolve the cloud host, the TLS handshake fails, the 10s client timeout expires, or ctx is cancelled mid-request.
Common situations: Container has no outbound internet access; corporate proxy/firewall blocks doligence.dozzle.dev; DNS misconfiguration in Docker networks; a custom DOLIGENCE_URL pointing at an unreachable host.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- (await res.json().catch(() =>
- (await res.json().catch(() =>
- deadline exceeded: with
- webhook notification failed
- failed to exchange token
AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07).
Data as JSON: /api/errors/d80407b274e33ff7.
Report an issue: GitHub.
Appendix: source
Thrown at internal/notification/dispatcher/cloud.go:94
}
payload, err := json.Marshal(notification)
if err != nil {
return fmt.Errorf("failed to marshal notification: %w", err)
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.URL, bytes.NewReader(payload))
if err != nil {
return fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", UserAgent)
req.Header.Set("X-API-Key", c.APIKey)
resp, err := c.client.Do(req)
if err != nil {
return fmt.Errorf("failed to send to cloud: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusTooManyRequests {
retryAfter := defaultRetryAfter
if ra := resp.Header.Get("Retry-After"); ra != "" {
if seconds, err := strconv.Atoi(ra); err == nil {
retryAfter = time.Duration(seconds) * time.Second
}
}
c.blockedUntil.Store(time.Now().Add(retryAfter).UnixNano())
log.Warn().
Str("cloud", c.Name).
Dur("retry_after", retryAfter).
Msg("rate limited by cloud, circuit breaker tripped")
return fmt.Errorf("cloud rate limited, backing off for %s", retryAfter)
}
View on GitHub (pinned to d9463cbe21)