{"record":{"id":"b03fabb37343dddb","repo":"Sonarr/Sonarr","slug":"unable-to-send-text-message-0","errorCode":null,"errorMessage":"Unable to send text message: {0}","messagePattern":"Unable to send text message: (.+?)","errorType":"exception","errorClass":"NtfyException","httpStatus":null,"severity":"error","filePath":"src/NzbDrone.Core/Notifications/Ntfy/NtfyProxy.cs","lineNumber":157,"sourceCode":"\n                foreach (var header in settings.Headers)\n                {\n                    requestBuilder.Headers.Add(header.Key, header.Value);\n                }\n\n                var request = requestBuilder.Build();\n\n                _httpClient.Execute(request);\n            }\n            catch (HttpException ex)\n            {\n                if (ex.Response.StatusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden)\n                {\n                    _logger.Error(ex, \"Authorization is required\");\n                    throw;\n                }\n\n                throw new NtfyException(\"Unable to send text message: {0}\", ex, ex.Message);\n            }\n        }\n    }\n}\n","sourceCodeStart":139,"sourceCodeEnd":162,"githubUrl":"https://github.com/Sonarr/Sonarr/blob/da2284d7eaab22ed9b2ca698af690148d691e967/src/NzbDrone.Core/Notifications/Ntfy/NtfyProxy.cs#L139-L162","documentation":"NtfyException(\"Unable to send text message: {0}\") is thrown when an HttpException occurs during a single-topic send and the status code is NOT 401 Unauthorized or 403 Forbidden (those are re-thrown unchanged at line 154 so auth errors propagate distinctly). The {0} is filled with ex.Message. This is the general HTTP-failure path for a single ntfy topic publish.","triggerScenarios":"The private SendNotification (line 113) executes the HTTP request to {serverUrl}/{topic} and catches HttpException. If the status is anything other than 401/403 (e.g. 404, 405, 422, 500, 502, 503), it wraps the error into NtfyException with the server's message.","commonSituations":"Self-hosted ntfy server URL is wrong (404). The ntfy server does not allow POST on that path (405). Server-side error (5xx). The ServerUrl points to a path that is not an ntfy instance. Topic name contains invalid path characters. Attachments or priority param malformed.","solutions":["Read the wrapped ex.Message (shown via {0}) to get the ntfy server's specific error text.","Verify settings.ServerUrl is the correct base URL of an ntfy instance (e.g. https://ntfy.sh or https://your-host), with no trailing path.","Confirm the topic name uses only allowed characters (alphanumeric, hyphen, underscore).","For self-hosted servers, check ntfy server logs for the corresponding request error.","For 5xx, retry; check the ntfy server health."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Validate server URL and topic before sending\nif (settings.ServerUrl.IsNotNullOrWhiteSpace() && !Uri.TryCreate(settings.ServerUrl, UriKind.Absolute, out _))\n{\n    return new ValidationFailure(\"ServerUrl\", \"Ntfy server URL is invalid.\");\n}","typeGuard":"public static bool IsNtfyHttp(Exception ex) => ex is Ntfy.NtfyException && !ex.Message.Contains(\"all topics\");","tryCatchPattern":"// Auth errors (401/403) propagate as HttpException; other HTTP errors become NtfyException\ncatch (NtfyException ex)\n{\n    _logger.Error(ex, \"Ntfy send failed: {0}\", ex.Message);\n    return new ValidationFailure(\"ServerUrl\", ex.Message);\n}","preventionTips":["Distinguish 401/403 (re-thrown as HttpException) from other HTTP errors (wrapped as NtfyException).","Verify the ServerUrl points to a real ntfy instance.","Ensure topic names use only allowed characters."],"tags":["ntfy","notifications","network","http","csharp"],"backgroundTag":null,"analyzedSha":"da2284d7eaab22ed9b2ca698af690148d691e967","analyzedAt":"2026-08-13T15:53:02.562Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}