{"record":{"id":"d432f7114f703e11","repo":"amir20/dozzle","slug":"cloud-returned-status-code-d-s","errorCode":null,"errorMessage":"cloud returned status code %d: %s","messagePattern":"cloud returned status code (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":401,"severity":"error","filePath":"internal/notification/dispatcher/cloud.go","lineNumber":122,"sourceCode":"\t\t}\n\t\tc.blockedUntil.Store(time.Now().Add(retryAfter).UnixNano())\n\t\tlog.Warn().\n\t\t\tStr(\"cloud\", c.Name).\n\t\t\tDur(\"retry_after\", retryAfter).\n\t\t\tMsg(\"rate limited by cloud, circuit breaker tripped\")\n\t\treturn fmt.Errorf(\"cloud rate limited, backing off for %s\", retryAfter)\n\t}\n\n\tif resp.StatusCode == http.StatusUnauthorized || resp.StatusCode == http.StatusForbidden {\n\t\tlimitedReader := io.LimitReader(resp.Body, 1024*1024)\n\t\tresponseBody, _ := io.ReadAll(limitedReader)\n\t\tc.blockedUntil.Store(time.Now().Add(unauthorizedRetryAfter).UnixNano())\n\t\tlog.Warn().\n\t\t\tStr(\"cloud\", c.Name).\n\t\t\tInt(\"status_code\", resp.StatusCode).\n\t\t\tDur(\"retry_after\", unauthorizedRetryAfter).\n\t\t\tMsg(\"cloud rejected API key, circuit breaker tripped\")\n\t\treturn fmt.Errorf(\"cloud returned status code %d: %s\", resp.StatusCode, string(responseBody))\n\t}\n\n\tif resp.StatusCode < 200 || resp.StatusCode >= 300 {\n\t\tlimitedReader := io.LimitReader(resp.Body, 1024*1024)\n\t\tresponseBody, _ := io.ReadAll(limitedReader)\n\t\tlog.Debug().\n\t\t\tStr(\"cloud\", c.Name).\n\t\t\tStr(\"url\", c.URL).\n\t\t\tInt(\"status_code\", resp.StatusCode).\n\t\t\tStr(\"payload\", string(payload)).\n\t\t\tStr(\"response_body\", string(responseBody)).\n\t\t\tMsg(\"cloud returned non-success status code\")\n\t\treturn fmt.Errorf(\"cloud returned status code %d: %s\", resp.StatusCode, string(responseBody))\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/amir20/dozzle/blob/d9463cbe21874e44ab79db6fa63e746ca7d22928/internal/notification/dispatcher/cloud.go#L104-L140","documentation":"Dozzle Cloud rejected the request with HTTP 401 Unauthorized or 403 Forbidden. The dispatcher reads up to 1MB of the response body, sets a 6-hour backoff (unauthorizedRetryAfter) because retrying cannot help until the key is fixed, and returns this error including the status code and body text.","triggerScenarios":"CloudDispatcher.Send received 401/403 from cloud, typically because the configured API key is invalid, revoked, or expired (ExpiresAt passed), or the account lacks the plan/permission for this endpoint.","commonSituations":"Rotated or deleted API key still configured in the dispatcher; expired subscription; key copied with whitespace or from the wrong account; cloud plan downgraded removing notification access.","solutions":["Generate a new API key in Dozzle Cloud and update the dispatcher configuration (recreating it also resets the 6h breaker)","Verify the key has no stray whitespace and belongs to the correct account","Check your cloud subscription/plan status and expiry","If the key was fixed out-of-band, call ResetBreaker() after a successful status check instead of waiting 6 hours"],"exampleFix":"// before\ndispatcher, _ := NewCloudDispatcher(\"cloud\", oldKey, \"\", nil)\n// after\ndispatcher, _ := NewCloudDispatcher(\"cloud\", newlyGeneratedKey, \"\", nil)","handlingStrategy":"validation","validationCode":"if apiKey == nil || strings.TrimSpace(apiKey) == \"\" {\n    return errors.New(\"cloud API key missing\")\n}","typeGuard":null,"tryCatchPattern":"if err := d.Send(ctx, n); err != nil && strings.Contains(err.Error(), \"status code 40\") {\n    // stop retrying; prompt user to regenerate the API key\n}","preventionTips":["Validate the API key at startup with a status check before wiring notifications","Rotate keys via config recreation (which resets the breaker)","Watch subscription expiry (ExpiresAt)"],"tags":["authentication","http-401","http-403","api-key","notifications"],"backgroundTag":"authentication-required","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"}